LEFT | RIGHT |
1 /* | 1 /* |
2 This file is part of LilyPond, the GNU music typesetter. | 2 This file is part of LilyPond, the GNU music typesetter. |
3 | 3 |
4 Copyright (C) 2005--2011 Han-Wen Nienhuys <hanwen@xs4all.nl> | 4 Copyright (C) 2005--2011 Han-Wen Nienhuys <hanwen@xs4all.nl> |
5 | 5 |
6 LilyPond is free software: you can redistribute it and/or modify | 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 | 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 | 8 the Free Software Foundation, either version 3 of the License, or |
9 (at your option) any later version. | 9 (at your option) any later version. |
10 | 10 |
11 LilyPond is distributed in the hope that it will be useful, | 11 LilyPond is distributed in the hope that it will be useful, |
12 but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 GNU General Public License for more details. | 14 GNU General Public License for more details. |
15 | 15 |
16 You should have received a copy of the GNU General Public License | 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/>. | 17 along with LilyPond. If not, see <http://www.gnu.org/licenses/>. |
18 */ | 18 */ |
19 | 19 |
20 #include "bar-line.hh" | |
21 #include "system.hh" | 20 #include "system.hh" |
22 #include "paper-column.hh" | 21 #include "paper-column.hh" |
23 #include "column-x-positions.hh" | 22 #include "column-x-positions.hh" |
24 #include "pointer-group-interface.hh" | 23 #include "pointer-group-interface.hh" |
25 #include "staff-spacing.hh" | 24 #include "staff-spacing.hh" |
26 #include "note-spacing.hh" | 25 #include "note-spacing.hh" |
27 #include "spacing-spanner.hh" | 26 #include "spacing-spanner.hh" |
28 #include "warn.hh" | 27 #include "warn.hh" |
29 #include "moment.hh" | 28 #include "moment.hh" |
30 #include "spacing-options.hh" | 29 #include "spacing-options.hh" |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
106 { | 105 { |
107 if (base_cols[j]->get_system () == which) | 106 if (base_cols[j]->get_system () == which) |
108 right = dynamic_cast<Item *> ((Grob *)base_cols[j]); | 107 right = dynamic_cast<Item *> ((Grob *)base_cols[j]); |
109 } | 108 } |
110 } | 109 } |
111 | 110 |
112 Grob *common = right->common_refpoint (left, X_AXIS); | 111 Grob *common = right->common_refpoint (left, X_AXIS); |
113 | 112 |
114 clique.push_back (right); | 113 clique.push_back (right); |
115 | 114 |
| 115 /* |
| 116 We use two vectors to keep track of loose column spacing: |
| 117 clique_spacing keeps track of ideal spaces. |
| 118 clique_tight_spacing keeps track of minimum spaces. |
| 119 Below, a scale factor is applied to the shifting of loose columns that |
| 120 aims to preserve clique_spacing but gets closer to clique_tight_spacing
as the |
| 121 space becomes smaller. This is used because the rods placed for loose c
olumns |
| 122 are tight (meaning they use minimum distances - see set_distances_for_lo
ose_columns). |
| 123 However, other rods may widen this distance, in which case we don't want
a crammed score. |
| 124 Thus, we aim for non-crammed, and fall back on crammed as needed. |
| 125 */ |
116 vector<Real> clique_spacing; | 126 vector<Real> clique_spacing; |
117 for (vsize j = 0; j + 1 < clique.size (); j++) | 127 vector<Real> clique_tight_spacing; |
| 128 clique_spacing.push_back (0.0); |
| 129 clique_tight_spacing.push_back (0.0); |
| 130 for (vsize j = 1; j + 1 < clique.size (); j++) |
118 { | 131 { |
119 Grob *clique_col = clique[j]; | 132 Grob *clique_col = clique[j]; |
120 | 133 |
121 Paper_column *loose_col = dynamic_cast<Paper_column *> (clique[j]); | 134 Paper_column *loose_col = dynamic_cast<Paper_column *> (clique[j]); |
122 Paper_column *next_col = dynamic_cast<Paper_column *> (clique[j + 1]); | 135 Paper_column *next_col = dynamic_cast<Paper_column *> (clique[j + 1]); |
123 | 136 |
124 Grob *spacing = unsmob_grob (clique_col->get_object ("spacing")); | 137 Grob *spacing = unsmob_grob (clique_col->get_object ("spacing")); |
125 if (Grob *grace_spacing = unsmob_grob (clique_col->get_object ("grace-
spacing"))) | 138 if (Grob *grace_spacing = unsmob_grob (clique_col->get_object ("grace-
spacing"))) |
126 { | 139 { |
127 spacing = grace_spacing; | 140 spacing = grace_spacing; |
128 } | 141 } |
129 | 142 |
130 Spacing_options options; | 143 Spacing_options options; |
131 if (spacing) | 144 if (spacing) |
132 options.init_from_grob (spacing); | 145 options.init_from_grob (spacing); |
133 else | 146 else |
134 programming_error ("Column without spacing object"); | 147 programming_error ("Column without spacing object"); |
135 | 148 |
136 /* | |
137 force a small space between the leftmost non-loose column and the le
ftmost loose-column | |
138 it is difficult to make this a grob | |
139 */ | |
140 ·········· | |
141 if (!j) | |
142 { | |
143 clique_spacing.push_back (options.left_loose_column_padding_); | |
144 continue; | |
145 } | |
146 Real base_note_space = 0.0; | 149 Real base_note_space = 0.0; |
| 150 Real tight_note_space = 0.0; |
147 | 151 |
148 if (Paper_column::is_musical (next_col) | 152 if (Paper_column::is_musical (next_col) |
149 && Paper_column::is_musical (loose_col)) | 153 && Paper_column::is_musical (loose_col)) |
150 base_note_space = Spacing_spanner::note_spacing (spacing, loose_col,
next_col, | 154 { |
151 &options); | 155 Real base = Spacing_spanner::note_spacing (spacing, loose_col, nex
t_col, |
| 156 &options); |
| 157 if (Note_spacing::has_interface (spacing)) |
| 158 { |
| 159 Spring spring = Note_spacing::get_spacing (spacing, next_col,
base, options.increment_);; |
| 160 base_note_space = spring.distance (); |
| 161 tight_note_space = spring.min_distance (); |
| 162 } |
| 163 else |
| 164 { |
| 165 base_note_space = base; |
| 166 tight_note_space = base; |
| 167 } |
| 168 } |
152 else | 169 else |
153 { | 170 { |
154 Spring spring = Spacing_spanner::standard_breakable_column_spacing
(spacing, | 171 Spring spring = Spacing_spanner::standard_breakable_column_spacing
(spacing, |
155 loose_col, next_col, | 172 loose_col, next_col, |
156 &options); | 173 &options); |
157 | 174 |
158 base_note_space = spring.distance (); | 175 base_note_space = spring.distance (); |
159 } | 176 tight_note_space = spring.min_distance (); |
160 | 177 } |
161 base_note_space = max (base_note_space, | |
162 robust_relative_extent (loose_col, loose_col, X
_AXIS)[RIGHT] | |
163 - robust_relative_extent (next_col, next_col, X
_AXIS)[LEFT]); | |
164 | 178 |
165 clique_spacing.push_back (base_note_space); | 179 clique_spacing.push_back (base_note_space); |
166 } | 180 clique_tight_spacing.push_back (tight_note_space); |
167 | 181 } |
| 182 |
| 183 Real permissible_distance = clique.back ()->relative_coordinate (common, X
_AXIS) - robust_relative_extent (clique[0], common, X_AXIS)[RIGHT]; |
168 Real right_point = robust_relative_extent (clique.back (), common, X_AXIS)
[LEFT]; | 184 Real right_point = robust_relative_extent (clique.back (), common, X_AXIS)
[LEFT]; |
169 | |
170 Grob *finished_right_column = clique.back (); | 185 Grob *finished_right_column = clique.back (); |
171 | 186 |
172 Real total_pushing = 0.0; | 187 Real sum_tight_spacing = 0; |
173 for (vsize j = 0; j < clique_spacing.size (); j++) | 188 Real sum_spacing = 0; |
174 total_pushing += clique_spacing[j]; | 189 // currently a magic number - what would be a good grob to hold this prope
rty? |
175 | 190 Real left_padding = 0.15; |
176 Real permissable_distance = clique.back ()->relative_coordinate (common, X
_AXIS) - robust_relative_extent (clique[0], common, X_AXIS)[RIGHT]; | 191 for (vsize j = 0; j < clique_spacing.size (); j++) |
177 // We assume here that things shouldn't be pushed more to the left than ne
cessary, thus the max of 1.0 | 192 { |
178 Real scale_factor = min (1.0, permissable_distance / total_pushing); | 193 sum_tight_spacing += clique_tight_spacing[j]; |
179 /* | 194 sum_spacing += clique_spacing[j]; |
180 We don't mess with bar lines, as they may be used later to position volt
as and then made transparent. | 195 } |
181 This should likely be fixed in volta-bracket.cc and/or volta-engraver.cc
to get better bounds | 196 Real scale_factor = max (0.0, min (1.0, (permissible_distance - left_paddi
ng - sum_tight_spacing) / (sum_spacing - sum_tight_spacing))); |
182 so that this hack isn't necessary. | |
183 */ | |
184 for (vsize j = 0; j < clique.size (); j++) | |
185 { | |
186 extract_grob_set (clique[j], "elements", elts); | |
187 for (vsize k = 0; k < elts.size (); k++) | |
188 if (Bar_line::has_interface (elts[k])) | |
189 { | |
190 scale_factor = 1.0; | |
191 break; | |
192 } | |
193 if (scale_factor == 1.0) | |
194 break; | |
195 } | |
196 for (vsize j = clique.size () - 2; j > 0; j--) | 197 for (vsize j = clique.size () - 2; j > 0; j--) |
197 { | 198 { |
198 Paper_column *clique_col = dynamic_cast<Paper_column *> (clique[j]); | 199 Paper_column *clique_col = dynamic_cast<Paper_column *> (clique[j]); |
199 | 200 |
200 right_point = finished_right_column->relative_coordinate (common, X_AX
IS); | 201 right_point = finished_right_column->relative_coordinate (common, X_AX
IS); |
201 | 202 |
202 Real distance_to_next = clique_spacing[j] * scale_factor; | 203 Real distance_to_next = clique_tight_spacing[j] + (clique_spacing[j] -
clique_tight_spacing[j]) * scale_factor; |
203 | 204 |
204 Real my_offset = right_point - distance_to_next; | 205 Real my_offset = right_point - distance_to_next; |
205 | 206 |
206 clique_col->translate_axis (my_offset - clique_col->relative_coordinat
e (common, X_AXIS), X_AXIS); | 207 clique_col->translate_axis (my_offset - clique_col->relative_coordinat
e (common, X_AXIS), X_AXIS); |
207 | 208 |
208 finished_right_column = clique_col; | 209 finished_right_column = clique_col; |
209 } | 210 } |
210 } | 211 } |
211 } | 212 } |
212 | 213 |
LEFT | RIGHT |