Left: | ||
Right: |
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) 2000--2011 Han-Wen Nienhuys <hanwen@xs4all.nl> | 4 Copyright (C) 2000--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 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
43 { | 43 { |
44 SCM axes = me->get_property ("axes"); | 44 SCM axes = me->get_property ("axes"); |
45 if (!scm_is_pair (axes)) | 45 if (!scm_is_pair (axes)) |
46 programming_error ("axes should be nonempty"); | 46 programming_error ("axes should be nonempty"); |
47 | 47 |
48 for (SCM ax = axes; scm_is_pair (ax); ax = scm_cdr (ax)) | 48 for (SCM ax = axes; scm_is_pair (ax); ax = scm_cdr (ax)) |
49 { | 49 { |
50 Axis a = (Axis) scm_to_int (scm_car (ax)); | 50 Axis a = (Axis) scm_to_int (scm_car (ax)); |
51 | 51 |
52 if (!e->get_parent (a)) | 52 if (!e->get_parent (a)) |
53 » e->set_parent (me, a); | 53 e->set_parent (me, a); |
54 | 54 |
55 e->set_object ((a == X_AXIS) | 55 e->set_object ((a == X_AXIS) |
56 » » ? ly_symbol2scm ("axis-group-parent-X") | 56 ? ly_symbol2scm ("axis-group-parent-X") |
57 » » : ly_symbol2scm ("axis-group-parent-Y"), | 57 : ly_symbol2scm ("axis-group-parent-Y"), |
58 » » me->self_scm ()); | 58 me->self_scm ()); |
59 } | 59 } |
60 | 60 |
61 /* must be ordered, because Align_interface also uses | 61 /* must be ordered, because Align_interface also uses |
62 Axis_group_interface */ | 62 Axis_group_interface */ |
63 Pointer_group_interface::add_grob (me, ly_symbol2scm ("elements"), e); | 63 Pointer_group_interface::add_grob (me, ly_symbol2scm ("elements"), e); |
64 } | 64 } |
65 | 65 |
66 bool | 66 bool |
67 Axis_group_interface::has_axis (Grob *me, Axis a) | 67 Axis_group_interface::has_axis (Grob *me, Axis a) |
68 { | 68 { |
69 SCM axes = me->get_property ("axes"); | 69 SCM axes = me->get_property ("axes"); |
70 | 70 |
71 return (SCM_BOOL_F != scm_memq (scm_from_int (a), axes)); | 71 return (SCM_BOOL_F != scm_memq (scm_from_int (a), axes)); |
72 } | 72 } |
73 | 73 |
74 Interval | 74 Interval |
75 Axis_group_interface::relative_group_extent (vector<Grob*> const &elts, | 75 Axis_group_interface::relative_group_extent (vector<Grob *> const &elts, |
76 Grob *common, Axis a) | 76 Grob *common, Axis a) |
77 { | 77 { |
78 return relative_maybe_core_group_extent (elts, common, a, false); | 78 return relative_maybe_bound_group_extent (elts, common, a, false); |
79 } | 79 } |
80 | 80 |
81 Interval | 81 Interval |
82 Axis_group_interface::relative_maybe_core_group_extent (vector<Grob*> const &elt s, | 82 Axis_group_interface::relative_maybe_bound_group_extent (vector<Grob*> const &el ts, |
Neil Puttock
2011/08/14 21:01:24
vector<Grob *>
| |
83 Grob *common, Axis a, bo ol core) | 83 Grob *common, Axis a, bo ol bound) |
84 { | 84 { |
85 Interval r; | 85 Interval r; |
86 for (vsize i = 0; i < elts.size (); i++) | 86 for (vsize i = 0; i < elts.size (); i++) |
87 { | 87 { |
88 Grob *se = elts[i]; | 88 Grob *se = elts[i]; |
89 if (!to_boolean (se->get_property ("cross-staff"))) | 89 if (!to_boolean (se->get_property ("cross-staff"))) |
90 » { | 90 { |
91 » Interval dims = (core && has_interface (se) | 91 Interval dims = (bound && has_interface (se) |
92 » ? generic_core_extent (se, common, a) | 92 ? generic_bound_extent (se, common, a) |
93 » : se->extent (common, a)); | 93 : se->extent (common, a)); |
94 » if (!dims.is_empty ()) | 94 if (!dims.is_empty ()) |
95 » r.unite (dims); | 95 r.unite (dims); |
96 » } | 96 } |
97 } | 97 } |
98 return r; | 98 return r; |
99 } | |
100 | |
101 Interval | |
102 Axis_group_interface::generic_bound_extent (Grob *me, Grob *common, Axis a) | |
103 { | |
104 /* trigger the callback to do skyline-spacing on the children */ | |
105 if (a == Y_AXIS) | |
106 (void) me->get_property ("vertical-skylines"); | |
107 | |
108 extract_grob_set (me, "elements", elts); | |
109 vector<Grob*> new_elts; | |
Neil Puttock
2011/08/14 21:01:24
vector<Grob *>
| |
110 | |
111 SCM interfaces = me->get_property ("bound-alignment-interfaces"); | |
112 | |
113 for (vsize i = 0; i < elts.size (); i++) | |
114 for (SCM l = interfaces; scm_is_pair (l); l = scm_cdr (l)) | |
115 if (elts[i]->internal_has_interface (scm_car (l))) | |
116 new_elts.push_back (elts[i]); | |
117 | |
118 if (new_elts.size () == 0) | |
Neil Puttock
2011/08/14 21:01:24
!new_elts.size ()
| |
119 return robust_relative_extent (me, common, a); | |
120 | |
121 if (!common) | |
122 common = common_refpoint_of_array (new_elts, me, a); | |
123 | |
124 return relative_maybe_bound_group_extent (new_elts, common, a, true); | |
99 } | 125 } |
100 | 126 |
101 Interval | 127 Interval |
102 Axis_group_interface::sum_partial_pure_heights (Grob *me, int start, int end) | 128 Axis_group_interface::sum_partial_pure_heights (Grob *me, int start, int end) |
103 { | 129 { |
104 Interval iv = begin_of_line_pure_height (me, start); | 130 Interval iv = begin_of_line_pure_height (me, start); |
105 iv.unite (rest_of_line_pure_height (me, start, end)); | 131 iv.unite (rest_of_line_pure_height (me, start, end)); |
106 | 132 |
107 return iv; | 133 return iv; |
108 } | 134 } |
109 | 135 |
110 Interval | 136 Interval |
111 Axis_group_interface::part_of_line_pure_height (Grob *me, bool begin, int start, int end) | 137 Axis_group_interface::part_of_line_pure_height (Grob *me, bool begin, int start, int end) |
112 { | 138 { |
113 Spanner *sp = dynamic_cast<Spanner*> (me); | 139 Spanner *sp = dynamic_cast<Spanner *> (me); |
114 SCM cache_symbol = begin | 140 SCM cache_symbol = begin |
115 ? ly_symbol2scm ("begin-of-line-pure-height") | 141 ? ly_symbol2scm ("begin-of-line-pure-height") |
116 : ly_symbol2scm ("rest-of-line-pure-height"); | 142 : ly_symbol2scm ("rest-of-line-pure-height"); |
117 SCM cached = sp->get_cached_pure_property (cache_symbol, start, end); | 143 SCM cached = sp->get_cached_pure_property (cache_symbol, start, end); |
118 if (scm_is_pair (cached)) | 144 if (scm_is_pair (cached)) |
119 return robust_scm2interval (cached, Interval (0, 0)); | 145 return robust_scm2interval (cached, Interval (0, 0)); |
120 | 146 |
121 SCM adjacent_pure_heights = me->get_property ("adjacent-pure-heights"); | 147 SCM adjacent_pure_heights = me->get_property ("adjacent-pure-heights"); |
122 Interval ret; | 148 Interval ret; |
123 | 149 |
124 if (!scm_is_pair (adjacent_pure_heights)) | 150 if (!scm_is_pair (adjacent_pure_heights)) |
125 ret = Interval (0, 0); | 151 ret = Interval (0, 0); |
126 else | 152 else |
127 { | 153 { |
128 SCM these_pure_heights = begin | 154 SCM these_pure_heights = begin |
129 » ? scm_car (adjacent_pure_heights) | 155 ? scm_car (adjacent_pure_heights) |
130 » : scm_cdr (adjacent_pure_heights); | 156 : scm_cdr (adjacent_pure_heights); |
131 | 157 |
132 if (scm_is_vector (these_pure_heights)) | 158 if (scm_is_vector (these_pure_heights)) |
133 » ret = combine_pure_heights (me, these_pure_heights, start, end); | 159 ret = combine_pure_heights (me, these_pure_heights, start, end); |
134 else | 160 else |
135 » ret = Interval (0, 0); | 161 ret = Interval (0, 0); |
136 } | 162 } |
137 | 163 |
138 sp->cache_pure_property (cache_symbol, start, end, ly_interval2scm (ret)); | 164 sp->cache_pure_property (cache_symbol, start, end, ly_interval2scm (ret)); |
139 return ret; | 165 return ret; |
140 } | 166 } |
141 | 167 |
142 Interval | 168 Interval |
143 Axis_group_interface::begin_of_line_pure_height (Grob *me, int start) | 169 Axis_group_interface::begin_of_line_pure_height (Grob *me, int start) |
144 { | 170 { |
145 return part_of_line_pure_height (me, true, start, start + 1); | 171 return part_of_line_pure_height (me, true, start, start + 1); |
146 } | 172 } |
147 | 173 |
148 Interval | 174 Interval |
149 Axis_group_interface::rest_of_line_pure_height (Grob *me, int start, int end) | 175 Axis_group_interface::rest_of_line_pure_height (Grob *me, int start, int end) |
150 { | 176 { |
151 return part_of_line_pure_height (me, false, start, end); | 177 return part_of_line_pure_height (me, false, start, end); |
152 } | 178 } |
153 | 179 |
154 Interval | 180 Interval |
155 Axis_group_interface::combine_pure_heights (Grob *me, SCM measure_extents, int s tart, int end) | 181 Axis_group_interface::combine_pure_heights (Grob *me, SCM measure_extents, int s tart, int end) |
156 { | 182 { |
157 Paper_score *ps = get_root_system (me)->paper_score (); | 183 Paper_score *ps = get_root_system (me)->paper_score (); |
158 vector<vsize> breaks = ps->get_break_indices (); | 184 vector<vsize> breaks = ps->get_break_indices (); |
159 vector<Grob*> cols = ps->get_columns (); | 185 vector<Grob *> cols = ps->get_columns (); |
160 | 186 |
161 Interval ext; | 187 Interval ext; |
162 for (vsize i = 0; i + 1 < breaks.size (); i++) | 188 for (vsize i = 0; i + 1 < breaks.size (); i++) |
163 { | 189 { |
164 int r = Paper_column::get_rank (cols[breaks[i]]); | 190 int r = Paper_column::get_rank (cols[breaks[i]]); |
165 if (r >= end) | 191 if (r >= end) |
166 » break; | 192 break; |
167 | 193 |
168 if (r >= start) | 194 if (r >= start) |
169 » ext.unite (ly_scm2interval (scm_c_vector_ref (measure_extents, i))); | 195 ext.unite (ly_scm2interval (scm_c_vector_ref (measure_extents, i))); |
170 } | 196 } |
171 | 197 |
172 return ext; | 198 return ext; |
173 } | 199 } |
174 | 200 |
175 // adjacent-pure-heights is a pair of vectors, each of which has one element | 201 // adjacent-pure-heights is a pair of vectors, each of which has one element |
176 // for every measure in the score. The first vector stores, for each measure, | 202 // for every measure in the score. The first vector stores, for each measure, |
177 // the combined height of the elements that are present only when the bar | 203 // the combined height of the elements that are present only when the bar |
178 // is at the beginning of a line. The second vector stores, for each measure, | 204 // is at the beginning of a line. The second vector stores, for each measure, |
179 // the combined height of the elements that are present only when the bar | 205 // the combined height of the elements that are present only when the bar |
(...skipping 15 matching lines...) Expand all Loading... | |
195 vector<Interval> begin_line_staff_heights; | 221 vector<Interval> begin_line_staff_heights; |
196 vector<Interval> mid_line_staff_heights; | 222 vector<Interval> mid_line_staff_heights; |
197 begin_line_heights.resize (ranks.size () - 1); | 223 begin_line_heights.resize (ranks.size () - 1); |
198 mid_line_heights.resize (ranks.size () - 1); | 224 mid_line_heights.resize (ranks.size () - 1); |
199 | 225 |
200 for (vsize i = 0; i < elts.size (); ++i) | 226 for (vsize i = 0; i < elts.size (); ++i) |
201 { | 227 { |
202 Grob *g = elts[i]; | 228 Grob *g = elts[i]; |
203 | 229 |
204 if (to_boolean (g->get_property ("cross-staff"))) | 230 if (to_boolean (g->get_property ("cross-staff"))) |
205 » continue; | 231 continue; |
206 | 232 |
207 bool outside_staff = scm_is_number (g->get_property ("outside-staff-priori ty")); | 233 bool outside_staff = scm_is_number (g->get_property ("outside-staff-priori ty")); |
208 Real padding = robust_scm2double (g->get_property ("outside-staff-padding" ), 0.5); | 234 Real padding = robust_scm2double (g->get_property ("outside-staff-padding" ), 0.5); |
209 | 235 |
210 // When we encounter the first outside-staff grob, make a copy | 236 // When we encounter the first outside-staff grob, make a copy |
211 // of the current heights to use as an estimate for the staff heights. | 237 // of the current heights to use as an estimate for the staff heights. |
212 // Note that the outside-staff approximation that we use here doesn't | 238 // Note that the outside-staff approximation that we use here doesn't |
213 // consider any collisions that might occur between outside-staff grobs, | 239 // consider any collisions that might occur between outside-staff grobs, |
214 // but only the fact that outside-staff grobs may need to be raised above | 240 // but only the fact that outside-staff grobs may need to be raised above |
215 // the staff. | 241 // the staff. |
216 if (outside_staff && begin_line_staff_heights.empty ()) | 242 if (outside_staff && begin_line_staff_heights.empty ()) |
217 » { | 243 { |
218 » begin_line_staff_heights = begin_line_heights; | 244 begin_line_staff_heights = begin_line_heights; |
219 » mid_line_staff_heights = mid_line_heights; | 245 mid_line_staff_heights = mid_line_heights; |
220 » } | 246 } |
221 | 247 |
222 // TODO: consider a pure version of get_grob_direction? | 248 // TODO: consider a pure version of get_grob_direction? |
223 Direction d = to_dir (g->get_property_data ("direction")); | 249 Direction d = to_dir (g->get_property_data ("direction")); |
224 d = (d == CENTER) ? UP : d; | 250 d = (d == CENTER) ? UP : d; |
225 | 251 |
226 Interval_t<int> rank_span = g->spanned_rank_interval (); | 252 Interval_t<int> rank_span = g->spanned_rank_interval (); |
227 vsize first_break = lower_bound (ranks, (vsize)rank_span[LEFT], less<vsize > ()); | 253 vsize first_break = lower_bound (ranks, (vsize)rank_span[LEFT], less<vsize > ()); |
228 if (first_break > 0 && ranks[first_break] >= (vsize)rank_span[LEFT]) | 254 if (first_break > 0 && ranks[first_break] >= (vsize)rank_span[LEFT]) |
229 » first_break--; | 255 first_break--; |
230 | 256 |
231 for (vsize j = first_break; j+1 < ranks.size () && (int)ranks[j] <= rank_s pan[RIGHT]; ++j) | 257 for (vsize j = first_break; j + 1 < ranks.size () && (int)ranks[j] <= rank _span[RIGHT]; ++j) |
232 » { | 258 { |
233 » int start = ranks[j]; | 259 int start = ranks[j]; |
234 » int end = ranks[j+1]; | 260 int end = ranks[j + 1]; |
235 | 261 |
236 » // Take grobs that are visible with respect to a slightly longer line. | 262 // Take grobs that are visible with respect to a slightly longer line. |
237 » // Otherwise, we will never include grobs at breakpoints which aren't | 263 // Otherwise, we will never include grobs at breakpoints which aren't |
238 » // end-of-line-visible. | 264 // end-of-line-visible. |
239 » int visibility_end = j + 2 < ranks.size () ? ranks[j+2] : end; | 265 int visibility_end = j + 2 < ranks.size () ? ranks[j + 2] : end; |
240 | 266 |
241 » if (g->pure_is_visible (start, visibility_end)) | 267 if (g->pure_is_visible (start, visibility_end)) |
242 » { | 268 { |
243 » Interval dims = g->pure_height (common, start, end); | 269 Interval dims = g->pure_height (common, start, end); |
244 » if (!dims.is_empty ()) | 270 if (!dims.is_empty ()) |
245 » » { | 271 { |
246 » » if (rank_span[LEFT] <= start) | 272 if (rank_span[LEFT] <= start) |
247 » » { | 273 { |
248 » » if (outside_staff) | 274 if (outside_staff) |
249 » » » begin_line_heights[j].unite ( | 275 begin_line_heights[j].unite (begin_line_staff_heights[j] .union_disjoint (dims, padding, d)); |
250 » » » begin_line_staff_heights[j].union_disjoint (dims, pa dding, d)); | 276 else |
251 » » else | 277 begin_line_heights[j].unite (dims); |
252 » » » begin_line_heights[j].unite (dims); | 278 } |
253 » » } | |
254 if (rank_span[RIGHT] > start) | 279 if (rank_span[RIGHT] > start) |
255 » » { | 280 { |
256 » » if (outside_staff) | 281 if (outside_staff) |
257 » » » mid_line_heights[j].unite ( | 282 mid_line_heights[j].unite (mid_line_staff_heights[j].uni on_disjoint (dims, padding, d)); |
258 mid_line_staff_heights[j].union_disjoint (dims, padd ing, d)); | 283 else |
259 » » else | 284 mid_line_heights[j].unite (dims); |
260 » » » mid_line_heights[j].unite (dims); | 285 } |
261 » » } | 286 } |
262 » » } | 287 } |
263 » } | 288 } |
264 » } | |
265 } | 289 } |
266 | 290 |
267 // Convert begin_line_heights and min_line_heights to SCM. | 291 // Convert begin_line_heights and min_line_heights to SCM. |
268 SCM begin_scm = scm_c_make_vector (ranks.size () - 1, SCM_EOL); | 292 SCM begin_scm = scm_c_make_vector (ranks.size () - 1, SCM_EOL); |
269 SCM mid_scm = scm_c_make_vector (ranks.size () - 1, SCM_EOL); | 293 SCM mid_scm = scm_c_make_vector (ranks.size () - 1, SCM_EOL); |
270 for (vsize i = 0; i < begin_line_heights.size (); ++i) | 294 for (vsize i = 0; i < begin_line_heights.size (); ++i) |
271 { | 295 { |
272 scm_vector_set_x (begin_scm, scm_from_int (i), ly_interval2scm (begin_line _heights[i])); | 296 scm_vector_set_x (begin_scm, scm_from_int (i), ly_interval2scm (begin_line _heights[i])); |
273 scm_vector_set_x (mid_scm, scm_from_int (i), ly_interval2scm (mid_line_hei ghts[i])); | 297 scm_vector_set_x (mid_scm, scm_from_int (i), ly_interval2scm (mid_line_hei ghts[i])); |
274 } | 298 } |
(...skipping 18 matching lines...) Expand all Loading... | |
293 | 317 |
294 Grob *common = unsmob_grob (me->get_object ("pure-Y-common")); | 318 Grob *common = unsmob_grob (me->get_object ("pure-Y-common")); |
295 extract_grob_set (me, "pure-relevant-grobs", elts); | 319 extract_grob_set (me, "pure-relevant-grobs", elts); |
296 | 320 |
297 Interval r; | 321 Interval r; |
298 for (vsize i = 0; i < elts.size (); i++) | 322 for (vsize i = 0; i < elts.size (); i++) |
299 { | 323 { |
300 Grob *g = elts[i]; | 324 Grob *g = elts[i]; |
301 Interval_t<int> rank_span = g->spanned_rank_interval (); | 325 Interval_t<int> rank_span = g->spanned_rank_interval (); |
302 if (rank_span[LEFT] <= end && rank_span[RIGHT] >= start | 326 if (rank_span[LEFT] <= end && rank_span[RIGHT] >= start |
303 » && g->pure_is_visible (start, end) | 327 && g->pure_is_visible (start, end) |
304 » && !to_boolean (g->get_property ("cross-staff"))) | 328 && !to_boolean (g->get_property ("cross-staff"))) |
305 » { | 329 { |
306 » Interval dims = g->pure_height (common, start, end); | 330 Interval dims = g->pure_height (common, start, end); |
307 » if (!dims.is_empty ()) | 331 if (!dims.is_empty ()) |
308 » r.unite (dims); | 332 r.unite (dims); |
309 » } | 333 } |
310 } | 334 } |
311 return r; | 335 return r; |
312 } | 336 } |
313 | 337 |
314 MAKE_SCHEME_CALLBACK (Axis_group_interface, width, 1); | 338 MAKE_SCHEME_CALLBACK (Axis_group_interface, width, 1); |
315 SCM | 339 SCM |
316 Axis_group_interface::width (SCM smob) | 340 Axis_group_interface::width (SCM smob) |
317 { | 341 { |
318 Grob *me = unsmob_grob (smob); | 342 Grob *me = unsmob_grob (smob); |
319 return generic_group_extent (me, X_AXIS); | 343 return generic_group_extent (me, X_AXIS); |
(...skipping 10 matching lines...) Expand all Loading... | |
330 MAKE_SCHEME_CALLBACK (Axis_group_interface, pure_height, 3); | 354 MAKE_SCHEME_CALLBACK (Axis_group_interface, pure_height, 3); |
331 SCM | 355 SCM |
332 Axis_group_interface::pure_height (SCM smob, SCM start_scm, SCM end_scm) | 356 Axis_group_interface::pure_height (SCM smob, SCM start_scm, SCM end_scm) |
333 { | 357 { |
334 int start = robust_scm2int (start_scm, 0); | 358 int start = robust_scm2int (start_scm, 0); |
335 int end = robust_scm2int (end_scm, INT_MAX); | 359 int end = robust_scm2int (end_scm, INT_MAX); |
336 Grob *me = unsmob_grob (smob); | 360 Grob *me = unsmob_grob (smob); |
337 | 361 |
338 /* Maybe we are in the second pass of a two-pass spacing run. In that | 362 /* Maybe we are in the second pass of a two-pass spacing run. In that |
339 case, the Y-extent of a system is already given to us */ | 363 case, the Y-extent of a system is already given to us */ |
340 System *system = dynamic_cast<System*> (me); | 364 System *system = dynamic_cast<System *> (me); |
341 if (system) | 365 if (system) |
342 { | 366 { |
343 SCM line_break_details = system->column (start)->get_property ("line-break -system-details"); | 367 SCM line_break_details = system->column (start)->get_property ("line-break -system-details"); |
344 SCM system_y_extent = scm_assq (ly_symbol2scm ("system-Y-extent"), line_br eak_details); | 368 SCM system_y_extent = scm_assq (ly_symbol2scm ("system-Y-extent"), line_br eak_details); |
345 if (scm_is_pair (system_y_extent)) | 369 if (scm_is_pair (system_y_extent)) |
346 » return scm_cdr (system_y_extent); | 370 return scm_cdr (system_y_extent); |
347 } | 371 } |
348 | 372 |
349 return ly_interval2scm (pure_group_height (me, start, end)); | 373 return ly_interval2scm (pure_group_height (me, start, end)); |
350 } | 374 } |
351 | 375 |
352 MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_skylines, 1); | 376 MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_skylines, 1); |
353 SCM | 377 SCM |
354 Axis_group_interface::calc_skylines (SCM smob) | 378 Axis_group_interface::calc_skylines (SCM smob) |
355 { | 379 { |
356 Grob *me = unsmob_grob (smob); | 380 Grob *me = unsmob_grob (smob); |
(...skipping 19 matching lines...) Expand all Loading... | |
376 Grob *x_common = common_refpoint_of_array (elements, me, X_AXIS); | 400 Grob *x_common = common_refpoint_of_array (elements, me, X_AXIS); |
377 | 401 |
378 if (y_common != me) | 402 if (y_common != me) |
379 programming_error ("combining skylines that don't belong to me"); | 403 programming_error ("combining skylines that don't belong to me"); |
380 | 404 |
381 Skyline_pair ret; | 405 Skyline_pair ret; |
382 for (vsize i = 0; i < elements.size (); i++) | 406 for (vsize i = 0; i < elements.size (); i++) |
383 { | 407 { |
384 SCM skyline_scm = elements[i]->get_property ("vertical-skylines"); | 408 SCM skyline_scm = elements[i]->get_property ("vertical-skylines"); |
385 if (Skyline_pair::unsmob (skyline_scm)) | 409 if (Skyline_pair::unsmob (skyline_scm)) |
386 » { | 410 { |
387 » Real offset = elements[i]->relative_coordinate (y_common, Y_AXIS); | 411 Real offset = elements[i]->relative_coordinate (y_common, Y_AXIS); |
388 » Skyline_pair other = *Skyline_pair::unsmob (skyline_scm); | 412 Skyline_pair other = *Skyline_pair::unsmob (skyline_scm); |
389 » other.raise (offset); | 413 other.raise (offset); |
390 » other.shift (elements[i]->relative_coordinate (x_common, X_AXIS)); | 414 other.shift (elements[i]->relative_coordinate (x_common, X_AXIS)); |
391 » ret.merge (other); | 415 ret.merge (other); |
392 » } | 416 } |
393 } | 417 } |
394 return ret.smobbed_copy (); | 418 return ret.smobbed_copy (); |
395 } | 419 } |
396 | 420 |
397 SCM | 421 SCM |
398 Axis_group_interface::generic_group_extent (Grob *me, Axis a) | 422 Axis_group_interface::generic_group_extent (Grob *me, Axis a) |
399 { | 423 { |
400 /* trigger the callback to do skyline-spacing on the children */ | 424 /* trigger the callback to do skyline-spacing on the children */ |
401 if (a == Y_AXIS) | 425 if (a == Y_AXIS) |
402 (void) me->get_property ("vertical-skylines"); | 426 (void) me->get_property ("vertical-skylines"); |
403 | 427 |
404 extract_grob_set (me, "elements", elts); | 428 extract_grob_set (me, "elements", elts); |
405 Grob *common = common_refpoint_of_array (elts, me, a); | 429 Grob *common = common_refpoint_of_array (elts, me, a); |
406 | 430 |
407 Real my_coord = me->relative_coordinate (common, a); | 431 Real my_coord = me->relative_coordinate (common, a); |
408 Interval r (relative_group_extent (elts, common, a)); | 432 Interval r (relative_group_extent (elts, common, a)); |
409 | 433 |
410 return ly_interval2scm (r - my_coord); | 434 return ly_interval2scm (r - my_coord); |
411 } | 435 } |
412 | 436 |
413 Interval | |
414 Axis_group_interface::generic_core_extent (Grob *me, Grob *common, Axis a) | |
415 { | |
416 /* trigger the callback to do skyline-spacing on the children */ | |
417 if (a == Y_AXIS) | |
418 (void) me->get_property ("vertical-skylines"); | |
419 | |
420 extract_grob_set (me, "elements", elts); | |
421 vector<Grob*> new_elts; | |
422 | |
423 SCM interfaces = me->get_property ("core-interfaces"); | |
424 | |
425 for (vsize i = 0; i < elts.size (); i++) | |
426 for (SCM l = interfaces; scm_is_pair (l); l = scm_cdr (l)) | |
427 if (elts[i]->internal_has_interface (scm_car (l))) | |
428 new_elts.push_back (elts[i]); | |
429 | |
430 if (!common) | |
431 common = common_refpoint_of_array (new_elts, me, a); | |
432 | |
433 return relative_maybe_core_group_extent (new_elts, common, a, true); | |
434 } | |
435 | |
436 /* This is like generic_group_extent, but it only counts the grobs that | 437 /* This is like generic_group_extent, but it only counts the grobs that |
437 are children of some other axis-group. This is uncached; if it becomes | 438 are children of some other axis-group. This is uncached; if it becomes |
438 commonly used, it may be necessary to cache it somehow. */ | 439 commonly used, it may be necessary to cache it somehow. */ |
439 Interval | 440 Interval |
440 Axis_group_interface::staff_extent (Grob *me, Grob *refp, Axis ext_a, Grob *staf f, Axis parent_a) | 441 Axis_group_interface::staff_extent (Grob *me, Grob *refp, Axis ext_a, Grob *staf f, Axis parent_a) |
441 { | 442 { |
442 extract_grob_set (me, "elements", elts); | 443 extract_grob_set (me, "elements", elts); |
443 vector<Grob*> new_elts; | 444 vector<Grob *> new_elts; |
444 | 445 |
445 for (vsize i = 0; i < elts.size (); i++) | 446 for (vsize i = 0; i < elts.size (); i++) |
446 if (elts[i]->common_refpoint (staff, parent_a) == staff) | 447 if (elts[i]->common_refpoint (staff, parent_a) == staff) |
447 new_elts.push_back (elts[i]); | 448 new_elts.push_back (elts[i]); |
448 | 449 |
449 return relative_group_extent (new_elts, refp, ext_a); | 450 return relative_group_extent (new_elts, refp, ext_a); |
450 } | 451 } |
451 | 452 |
452 | |
453 MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_pure_relevant_grobs, 1); | 453 MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_pure_relevant_grobs, 1); |
454 SCM | 454 SCM |
455 Axis_group_interface::calc_pure_relevant_grobs (SCM smob) | 455 Axis_group_interface::calc_pure_relevant_grobs (SCM smob) |
456 { | 456 { |
457 Grob *me = unsmob_grob (smob); | 457 Grob *me = unsmob_grob (smob); |
458 | 458 |
459 extract_grob_set (me, "elements", elts); | 459 extract_grob_set (me, "elements", elts); |
460 | 460 |
461 vector<Grob*> relevant_grobs; | 461 vector<Grob *> relevant_grobs; |
462 SCM pure_relevant_p = ly_lily_module_constant ("pure-relevant?"); | 462 SCM pure_relevant_p = ly_lily_module_constant ("pure-relevant?"); |
463 | 463 |
464 for (vsize i = 0; i < elts.size (); i++) | 464 for (vsize i = 0; i < elts.size (); i++) |
465 { | 465 { |
466 if (to_boolean (scm_apply_1 (pure_relevant_p, elts[i]->self_scm (), SCM_EO L))) | 466 if (to_boolean (scm_apply_1 (pure_relevant_p, elts[i]->self_scm (), SCM_EO L))) |
467 » relevant_grobs.push_back (elts[i]); | 467 relevant_grobs.push_back (elts[i]); |
468 | 468 |
469 if (Item *it = dynamic_cast<Item*> (elts[i])) | 469 if (Item *it = dynamic_cast<Item *> (elts[i])) |
470 » { | 470 { |
471 » Direction d = LEFT; | 471 Direction d = LEFT; |
472 » do | 472 do |
473 » { | 473 { |
474 » Item *piece = it->find_prebroken_piece (d); | 474 Item *piece = it->find_prebroken_piece (d); |
475 » if (piece && to_boolean (scm_apply_1 (pure_relevant_p, piece->self _scm (), SCM_EOL))) | 475 if (piece && to_boolean (scm_apply_1 (pure_relevant_p, piece->self _scm (), SCM_EOL))) |
476 » » relevant_grobs.push_back (piece); | 476 relevant_grobs.push_back (piece); |
477 » } | 477 } |
478 » while (flip (&d) != LEFT); | 478 while (flip (&d) != LEFT); |
479 » } | 479 } |
480 } | 480 } |
481 | 481 |
482 vector_sort (relevant_grobs, pure_staff_priority_less); | 482 vector_sort (relevant_grobs, pure_staff_priority_less); |
483 SCM grobs_scm = Grob_array::make_array (); | 483 SCM grobs_scm = Grob_array::make_array (); |
484 unsmob_grob_array (grobs_scm)->set_array (relevant_grobs); | 484 unsmob_grob_array (grobs_scm)->set_array (relevant_grobs); |
485 | 485 |
486 return grobs_scm; | 486 return grobs_scm; |
487 } | 487 } |
488 | 488 |
489 MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_pure_y_common, 1); | 489 MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_pure_y_common, 1); |
(...skipping 20 matching lines...) Expand all Loading... | |
510 Grob *common = common_refpoint_of_array (elts, me, axis); | 510 Grob *common = common_refpoint_of_array (elts, me, axis); |
511 if (!common) | 511 if (!common) |
512 { | 512 { |
513 me->programming_error ("No common parent found in calc_common axis."); | 513 me->programming_error ("No common parent found in calc_common axis."); |
514 return SCM_EOL; | 514 return SCM_EOL; |
515 } | 515 } |
516 | 516 |
517 return common->self_scm (); | 517 return common->self_scm (); |
518 } | 518 } |
519 | 519 |
520 | |
521 MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_x_common, 1); | 520 MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_x_common, 1); |
522 SCM | 521 SCM |
523 Axis_group_interface::calc_x_common (SCM grob) | 522 Axis_group_interface::calc_x_common (SCM grob) |
524 { | 523 { |
525 return calc_common (unsmob_grob (grob), X_AXIS); | 524 return calc_common (unsmob_grob (grob), X_AXIS); |
526 } | 525 } |
527 | 526 |
528 MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_y_common, 1); | 527 MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_y_common, 1); |
529 SCM | 528 SCM |
530 Axis_group_interface::calc_y_common (SCM grob) | 529 Axis_group_interface::calc_y_common (SCM grob) |
(...skipping 11 matching lines...) Expand all Loading... | |
542 programming_error ("no pure Y common refpoint"); | 541 programming_error ("no pure Y common refpoint"); |
543 return Interval (); | 542 return Interval (); |
544 } | 543 } |
545 Real my_coord = me->relative_coordinate (common, Y_AXIS); | 544 Real my_coord = me->relative_coordinate (common, Y_AXIS); |
546 Interval r (relative_pure_height (me, start, end)); | 545 Interval r (relative_pure_height (me, start, end)); |
547 | 546 |
548 return r - my_coord; | 547 return r - my_coord; |
549 } | 548 } |
550 | 549 |
551 void | 550 void |
552 Axis_group_interface::get_children (Grob *me, vector<Grob*> *found) | 551 Axis_group_interface::get_children (Grob *me, vector<Grob *> *found) |
553 { | 552 { |
554 found->push_back (me); | 553 found->push_back (me); |
555 | 554 |
556 if (!has_interface (me)) | 555 if (!has_interface (me)) |
557 return; | 556 return; |
558 | 557 |
559 extract_grob_set (me, "elements", elements); | 558 extract_grob_set (me, "elements", elements); |
560 for (vsize i = 0; i < elements.size (); i++) | 559 for (vsize i = 0; i < elements.size (); i++) |
561 { | 560 { |
562 Grob *e = elements[i]; | 561 Grob *e = elements[i]; |
563 Axis_group_interface::get_children (e, found); | 562 Axis_group_interface::get_children (e, found); |
564 } | 563 } |
565 } | 564 } |
566 | 565 |
567 static bool | 566 static bool |
568 staff_priority_less (Grob * const &g1, Grob * const &g2) | 567 staff_priority_less (Grob *const &g1, Grob *const &g2) |
569 { | 568 { |
570 Real priority_1 = robust_scm2double (g1->get_property ("outside-staff-priority "), -infinity_f); | 569 Real priority_1 = robust_scm2double (g1->get_property ("outside-staff-priority "), -infinity_f); |
571 Real priority_2 = robust_scm2double (g2->get_property ("outside-staff-priority "), -infinity_f); | 570 Real priority_2 = robust_scm2double (g2->get_property ("outside-staff-priority "), -infinity_f); |
572 | 571 |
573 if (priority_1 < priority_2) | 572 if (priority_1 < priority_2) |
574 return true; | 573 return true; |
575 else if (priority_1 > priority_2) | 574 else if (priority_1 > priority_2) |
576 return false; | 575 return false; |
577 | 576 |
578 /* if neither grob has an outside-staff priority, the ordering will have no | 577 /* if neither grob has an outside-staff priority, the ordering will have no |
579 effect -- we just need to choose a consistent ordering. We do this to | 578 effect -- we just need to choose a consistent ordering. We do this to |
580 avoid the side-effect of calculating extents. */ | 579 avoid the side-effect of calculating extents. */ |
581 if (isinf (priority_1)) | 580 if (isinf (priority_1)) |
582 return g1 < g2; | 581 return g1 < g2; |
583 | 582 |
584 /* if there is no preference in staff priority, choose the left-most one */ | 583 /* if there is no preference in staff priority, choose the left-most one */ |
585 Grob *common = g1->common_refpoint (g2, X_AXIS); | 584 Grob *common = g1->common_refpoint (g2, X_AXIS); |
586 Real start_1 = g1->extent (common, X_AXIS)[LEFT]; | 585 Real start_1 = g1->extent (common, X_AXIS)[LEFT]; |
587 Real start_2 = g2->extent (common, X_AXIS)[LEFT]; | 586 Real start_2 = g2->extent (common, X_AXIS)[LEFT]; |
588 return start_1 < start_2; | 587 return start_1 < start_2; |
589 } | 588 } |
590 | 589 |
591 static bool | 590 static bool |
592 pure_staff_priority_less (Grob * const &g1, Grob * const &g2) | 591 pure_staff_priority_less (Grob *const &g1, Grob *const &g2) |
593 { | 592 { |
594 Real priority_1 = robust_scm2double (g1->get_property ("outside-staff-priority "), -infinity_f); | 593 Real priority_1 = robust_scm2double (g1->get_property ("outside-staff-priority "), -infinity_f); |
595 Real priority_2 = robust_scm2double (g2->get_property ("outside-staff-priority "), -infinity_f); | 594 Real priority_2 = robust_scm2double (g2->get_property ("outside-staff-priority "), -infinity_f); |
596 | 595 |
597 return priority_1 < priority_2; | 596 return priority_1 < priority_2; |
598 } | 597 } |
599 | 598 |
600 static void | 599 static void |
601 add_boxes (Grob *me, Grob *x_common, Grob *y_common, vector<Box> *const boxes, S kyline_pair *skylines) | 600 add_boxes (Grob *me, Grob *x_common, Grob *y_common, vector<Box> *const boxes, S kyline_pair *skylines) |
602 { | 601 { |
603 /* if a child has skylines, use them instead of the extent box */ | 602 /* if a child has skylines, use them instead of the extent box */ |
604 if (Skyline_pair *pair = Skyline_pair::unsmob (me->get_property ("vertical-sky lines"))) | 603 if (Skyline_pair *pair = Skyline_pair::unsmob (me->get_property ("vertical-sky lines"))) |
605 { | 604 { |
606 Skyline_pair s = *pair; | 605 Skyline_pair s = *pair; |
607 s.shift (me->relative_coordinate (x_common, X_AXIS)); | 606 s.shift (me->relative_coordinate (x_common, X_AXIS)); |
608 s.raise (me->relative_coordinate (y_common, Y_AXIS)); | 607 s.raise (me->relative_coordinate (y_common, Y_AXIS)); |
609 skylines->merge (s); | 608 skylines->merge (s); |
610 } | 609 } |
611 else if (Grob_array *elements = unsmob_grob_array (me->get_object ("elements") )) | 610 else if (Grob_array *elements = unsmob_grob_array (me->get_object ("elements") )) |
612 { | 611 { |
613 for (vsize i = 0; i < elements->size (); i++) | 612 for (vsize i = 0; i < elements->size (); i++) |
614 » add_boxes (elements->grob (i), x_common, y_common, boxes, skylines); | 613 add_boxes (elements->grob (i), x_common, y_common, boxes, skylines); |
615 } | 614 } |
616 else if (!scm_is_number (me->get_property ("outside-staff-priority")) | 615 else if (!scm_is_number (me->get_property ("outside-staff-priority")) |
617 » && !to_boolean (me->get_property ("cross-staff"))) | 616 && !to_boolean (me->get_property ("cross-staff"))) |
618 { | 617 { |
619 boxes->push_back (Box (me->extent (x_common, X_AXIS), | 618 boxes->push_back (Box (me->extent (x_common, X_AXIS), |
620 » » » me->extent (y_common, Y_AXIS))); | 619 me->extent (y_common, Y_AXIS))); |
621 } | 620 } |
622 } | 621 } |
623 | 622 |
624 /* We want to avoid situations like this: | 623 /* We want to avoid situations like this: |
625 still more text | 624 still more text |
626 more text | 625 more text |
627 text | 626 text |
628 ------------------- | 627 ------------------- |
629 staff | 628 staff |
630 ------------------- | 629 ------------------- |
631 | 630 |
632 The point is that "still more text" should be positioned under | 631 The point is that "still more text" should be positioned under |
633 "more text". In order to achieve this, we place the grobs in several | 632 "more text". In order to achieve this, we place the grobs in several |
634 passes. We keep track of the right-most horizontal position that has been | 633 passes. We keep track of the right-most horizontal position that has been |
635 affected by the current pass so far (actually we keep track of 2 | 634 affected by the current pass so far (actually we keep track of 2 |
636 positions, one for above the staff, one for below). | 635 positions, one for above the staff, one for below). |
637 | 636 |
638 In each pass, we loop through the unplaced grobs from left to right. | 637 In each pass, we loop through the unplaced grobs from left to right. |
639 If the grob doesn't overlap the right-most affected position, we place it | 638 If the grob doesn't overlap the right-most affected position, we place it |
640 (and then update the right-most affected position to point to the right | 639 (and then update the right-most affected position to point to the right |
641 edge of the just-placed grob). Otherwise, we skip it until the next pass. | 640 edge of the just-placed grob). Otherwise, we skip it until the next pass. |
642 */ | 641 */ |
643 static void | 642 static void |
644 add_grobs_of_one_priority (Skyline_pair *const skylines, | 643 add_grobs_of_one_priority (Skyline_pair *const skylines, |
645 » » » vector<Grob*> elements, | 644 vector<Grob *> elements, |
646 » » » Grob *x_common, | 645 Grob *x_common, |
647 » » » Grob *y_common) | 646 Grob *y_common) |
648 { | 647 { |
649 vector<Box> boxes; | 648 vector<Box> boxes; |
650 Drul_array<Real> last_affected_position; | 649 Drul_array<Real> last_affected_position; |
651 | 650 |
652 reverse (elements); | 651 reverse (elements); |
653 while (!elements.empty ()) | 652 while (!elements.empty ()) |
654 { | 653 { |
655 last_affected_position[UP] = -infinity_f; | 654 last_affected_position[UP] = -infinity_f; |
656 last_affected_position[DOWN] = -infinity_f; | 655 last_affected_position[DOWN] = -infinity_f; |
657 /* do one pass */ | 656 /* do one pass */ |
658 for (vsize i = elements.size (); i--;) | 657 for (vsize i = elements.size (); i--;) |
659 » { | 658 { |
660 » Direction dir = get_grob_direction (elements[i]); | 659 Direction dir = get_grob_direction (elements[i]); |
661 » if (dir == CENTER) | 660 if (dir == CENTER) |
662 » { | 661 { |
663 » warning (_ ("an outside-staff object should have a direction, defa ulting to up")); | 662 warning (_ ("an outside-staff object should have a direction, defa ulting to up")); |
664 » dir = UP; | 663 dir = UP; |
665 » } | 664 } |
666 | 665 |
667 » Box b (elements[i]->extent (x_common, X_AXIS), | 666 Box b (elements[i]->extent (x_common, X_AXIS), |
668 » » elements[i]->extent (y_common, Y_AXIS)); | 667 elements[i]->extent (y_common, Y_AXIS)); |
669 » SCM horizon_padding_scm = elements[i]->get_property ("outside-staff-ho rizontal-padding"); | 668 SCM horizon_padding_scm = elements[i]->get_property ("outside-staff-ho rizontal-padding"); |
670 » Real horizon_padding = robust_scm2double (horizon_padding_scm, 0.0); | 669 Real horizon_padding = robust_scm2double (horizon_padding_scm, 0.0); |
671 | 670 |
672 » if (b[X_AXIS][LEFT] - 2*horizon_padding < last_affected_position[dir]) | 671 if (b[X_AXIS][LEFT] - 2 * horizon_padding < last_affected_position[dir ]) |
673 » continue; | 672 continue; |
674 | 673 |
675 » if (!b[X_AXIS].is_empty () && !b[Y_AXIS].is_empty ()) | 674 if (!b[X_AXIS].is_empty () && !b[Y_AXIS].is_empty ()) |
676 » { | 675 { |
677 » boxes.clear (); | 676 boxes.clear (); |
678 » boxes.push_back (b); | 677 boxes.push_back (b); |
679 » Skyline other = Skyline (boxes, horizon_padding, X_AXIS, -dir); | 678 Skyline other = Skyline (boxes, horizon_padding, X_AXIS, -dir); |
680 » Real padding = robust_scm2double (elements[i]->get_property ("outs ide-staff-padding"), 0.5); | 679 Real padding = robust_scm2double (elements[i]->get_property ("outs ide-staff-padding"), 0.5); |
681 » Real dist = (*skylines)[dir].distance (other) + padding; | 680 Real dist = (*skylines)[dir].distance (other) + padding; |
682 | 681 |
683 » if (dist > 0) | 682 if (dist > 0) |
684 » » { | 683 { |
685 » » b.translate (Offset (0, dir*dist)); | 684 b.translate (Offset (0, dir * dist)); |
686 » » elements[i]->translate_axis (dir*dist, Y_AXIS); | 685 elements[i]->translate_axis (dir * dist, Y_AXIS); |
687 » » } | 686 } |
688 » skylines->insert (b, 0, X_AXIS); | 687 skylines->insert (b, 0, X_AXIS); |
689 » elements[i]->set_property ("outside-staff-priority", SCM_BOOL_F); | 688 elements[i]->set_property ("outside-staff-priority", SCM_BOOL_F); |
690 » last_affected_position[dir] = b[X_AXIS][RIGHT]; | 689 last_affected_position[dir] = b[X_AXIS][RIGHT]; |
691 » } | 690 } |
692 | 691 |
693 » /* | 692 /* |
694 » Ugh: quadratic. --hwn | 693 Ugh: quadratic. --hwn |
695 » */ | 694 */ |
696 » elements.erase (elements.begin () + i); | 695 elements.erase (elements.begin () + i); |
697 » } | 696 } |
698 } | 697 } |
698 } | |
699 | |
700 bool | |
701 Axis_group_interface::has_outside_staff_parent (Grob *me) | |
702 { | |
703 return (me | |
704 ? (scm_is_number (me->get_property ("outside-staff-priority")) | |
705 || has_outside_staff_parent (me->get_parent (Y_AXIS))) | |
706 : false); | |
699 } | 707 } |
700 | 708 |
701 // TODO: it is tricky to correctly handle skyline placement of cross-staff grobs . | 709 // TODO: it is tricky to correctly handle skyline placement of cross-staff grobs . |
702 // For example, cross-staff beams cannot be formatted until the distance between | 710 // For example, cross-staff beams cannot be formatted until the distance between |
703 // staves is known and therefore any grobs that depend on the beam cannot be pla ced | 711 // staves is known and therefore any grobs that depend on the beam cannot be pla ced |
704 // until the skylines are known. On the other hand, the distance between staves should | 712 // until the skylines are known. On the other hand, the distance between staves should |
705 // really depend on position of the cross-staff grobs that lie between them. | 713 // really depend on position of the cross-staff grobs that lie between them. |
706 // Currently, we just leave cross-staff grobs out of the | 714 // Currently, we just leave cross-staff grobs out of the |
707 // skyline altogether, but this could mean that staves are placed so close toget her | 715 // skyline altogether, but this could mean that staves are placed so close toget her |
708 // that there is no room for the cross-staff grob. It also means, of course, tha t | 716 // that there is no room for the cross-staff grob. It also means, of course, tha t |
709 // we don't get the benefits of skyline placement for cross-staff grobs. | 717 // we don't get the benefits of skyline placement for cross-staff grobs. |
710 Skyline_pair | 718 Skyline_pair |
711 Axis_group_interface::skyline_spacing (Grob *me, vector<Grob*> elements) | 719 Axis_group_interface::skyline_spacing (Grob *me, vector<Grob *> elements) |
712 { | 720 { |
713 /* For grobs with an outside-staff-priority, the sorting function might | 721 /* For grobs with an outside-staff-priority, the sorting function might |
714 call extent and cause suicide. This breaks the contract that is required | 722 call extent and cause suicide. This breaks the contract that is required |
715 for the STL sort function. To avoid this, we make sure that any suicides | 723 for the STL sort function. To avoid this, we make sure that any suicides |
716 are triggered beforehand. | 724 are triggered beforehand. |
717 */ | 725 */ |
718 for (vsize i = 0; i < elements.size (); i++) | 726 for (vsize i = 0; i < elements.size (); i++) |
719 if (scm_is_number (elements[i]->get_property ("outside-staff-priority"))) | 727 if (scm_is_number (elements[i]->get_property ("outside-staff-priority"))) |
720 elements[i]->extent (elements[i], X_AXIS); | 728 elements[i]->extent (elements[i], X_AXIS); |
721 | 729 |
722 vector_sort (elements, staff_priority_less); | 730 vector_sort (elements, staff_priority_less); |
723 Grob *x_common = common_refpoint_of_array (elements, me, X_AXIS); | 731 Grob *x_common = common_refpoint_of_array (elements, me, X_AXIS); |
724 Grob *y_common = common_refpoint_of_array (elements, me, Y_AXIS); | 732 Grob *y_common = common_refpoint_of_array (elements, me, Y_AXIS); |
725 | 733 |
726 assert (y_common == me); | 734 assert (y_common == me); |
727 | 735 |
728 vsize i = 0; | 736 vsize i = 0; |
729 vector<Box> boxes; | 737 vector<Box> boxes; |
730 | 738 |
731 Skyline_pair skylines; | 739 Skyline_pair skylines; |
732 for (i = 0; i < elements.size () | 740 for (i = 0; i < elements.size () |
733 » && !scm_is_number (elements[i]->get_property ("outside-staff-priority") ); i++) | 741 && !scm_is_number (elements[i]->get_property ("outside-staff-priority")); i++) |
734 if (!to_boolean (elements[i]->get_property ("cross-staff"))) | 742 if (!(to_boolean (elements[i]->get_property ("cross-staff")) || has_outside_ staff_parent (elements[i]))) |
735 add_boxes (elements[i], x_common, y_common, &boxes, &skylines); | 743 add_boxes (elements[i], x_common, y_common, &boxes, &skylines); |
736 | 744 |
737 SCM padding_scm = me->get_property ("skyline-horizontal-padding"); | 745 SCM padding_scm = me->get_property ("skyline-horizontal-padding"); |
738 Real padding = robust_scm2double (padding_scm, 0.1); | 746 Real padding = robust_scm2double (padding_scm, 0.1); |
739 skylines.merge (Skyline_pair (boxes, padding, X_AXIS)); | 747 skylines.merge (Skyline_pair (boxes, padding, X_AXIS)); |
740 for (; i < elements.size (); i++) | 748 for (; i < elements.size (); i++) |
741 { | 749 { |
742 if (to_boolean (elements[i]->get_property ("cross-staff"))) | 750 if (to_boolean (elements[i]->get_property ("cross-staff"))) |
743 » continue; | 751 continue; |
744 | 752 |
745 SCM priority = elements[i]->get_property ("outside-staff-priority"); | 753 SCM priority = elements[i]->get_property ("outside-staff-priority"); |
746 vector<Grob*> current_elts; | 754 vector<Grob *> current_elts; |
747 current_elts.push_back (elements[i]); | 755 current_elts.push_back (elements[i]); |
748 while (i + 1 < elements.size () | 756 while (i + 1 < elements.size () |
749 » && scm_eq_p (elements[i+1]->get_property ("outside-staff-priority") , priority)) | 757 && scm_eq_p (elements[i + 1]->get_property ("outside-staff-priority "), priority)) |
750 » { | 758 { |
751 » if (!to_boolean (elements[i+1]->get_property ("cross-staff"))) | 759 if (!to_boolean (elements[i + 1]->get_property ("cross-staff"))) |
752 » current_elts.push_back (elements[i+1]); | 760 current_elts.push_back (elements[i + 1]); |
753 » ++i; | 761 ++i; |
754 » } | 762 } |
755 | 763 |
756 add_grobs_of_one_priority (&skylines, current_elts, x_common, y_common); | 764 add_grobs_of_one_priority (&skylines, current_elts, x_common, y_common); |
757 } | 765 } |
758 skylines.shift (-me->relative_coordinate (x_common, X_AXIS)); | 766 skylines.shift (-me->relative_coordinate (x_common, X_AXIS)); |
759 return skylines; | 767 return skylines; |
760 } | 768 } |
761 | 769 |
762 MAKE_SCHEME_CALLBACK (Axis_group_interface, print, 1) | 770 MAKE_SCHEME_CALLBACK (Axis_group_interface, print, 1) |
763 SCM | 771 SCM |
764 Axis_group_interface::print (SCM smob) | 772 Axis_group_interface::print (SCM smob) |
765 { | 773 { |
766 if (!debug_skylines) | 774 if (!debug_skylines) |
767 return SCM_BOOL_F; | 775 return SCM_BOOL_F; |
768 | 776 |
769 Grob *me = unsmob_grob (smob); | 777 Grob *me = unsmob_grob (smob); |
770 Stencil ret; | 778 Stencil ret; |
771 if (Skyline_pair *s = Skyline_pair::unsmob (me->get_property ("vertical-skylin es"))) | 779 if (Skyline_pair *s = Skyline_pair::unsmob (me->get_property ("vertical-skylin es"))) |
772 { | 780 { |
773 ret.add_stencil (Lookup::points_to_line_stencil (0.1, (*s)[UP].to_points ( X_AXIS)) | 781 ret.add_stencil (Lookup::points_to_line_stencil (0.1, (*s)[UP].to_points ( X_AXIS)) |
774 » » .in_color (255, 0, 255)); | 782 .in_color (255, 0, 255)); |
775 ret.add_stencil (Lookup::points_to_line_stencil (0.1, (*s)[DOWN].to_points (X_AXIS)) | 783 ret.add_stencil (Lookup::points_to_line_stencil (0.1, (*s)[DOWN].to_points (X_AXIS)) |
776 » » .in_color (0, 255, 255)); | 784 .in_color (0, 255, 255)); |
777 } | 785 } |
778 return ret.smobbed_copy (); | 786 return ret.smobbed_copy (); |
779 } | 787 } |
780 | 788 |
781 MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_pure_staff_staff_spacing, 3) | 789 MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_pure_staff_staff_spacing, 3) |
782 SCM | 790 SCM |
783 Axis_group_interface::calc_pure_staff_staff_spacing (SCM smob, SCM start, SCM en d) | 791 Axis_group_interface::calc_pure_staff_staff_spacing (SCM smob, SCM start, SCM en d) |
784 { | 792 { |
785 return calc_maybe_pure_staff_staff_spacing (unsmob_grob (smob), | 793 return calc_maybe_pure_staff_staff_spacing (unsmob_grob (smob), |
786 » » » » » true, | 794 true, |
787 » » » » » scm_to_int (start), | 795 scm_to_int (start), |
788 » » » » » scm_to_int (end)); | 796 scm_to_int (end)); |
789 } | 797 } |
790 | 798 |
791 MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_staff_staff_spacing, 1) | 799 MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_staff_staff_spacing, 1) |
792 SCM | 800 SCM |
793 Axis_group_interface::calc_staff_staff_spacing (SCM smob) | 801 Axis_group_interface::calc_staff_staff_spacing (SCM smob) |
794 { | 802 { |
795 return calc_maybe_pure_staff_staff_spacing (unsmob_grob (smob), | 803 return calc_maybe_pure_staff_staff_spacing (unsmob_grob (smob), |
796 » » » » » false, | 804 false, |
797 » » » » » 0, | 805 0, |
798 » » » » » INT_MAX); | 806 INT_MAX); |
799 } | 807 } |
800 | 808 |
801 SCM | 809 SCM |
802 Axis_group_interface::calc_maybe_pure_staff_staff_spacing (Grob *me, bool pure, int start, int end) | 810 Axis_group_interface::calc_maybe_pure_staff_staff_spacing (Grob *me, bool pure, int start, int end) |
803 { | 811 { |
804 Grob *grouper = unsmob_grob (me->get_object ("staff-grouper")); | 812 Grob *grouper = unsmob_grob (me->get_object ("staff-grouper")); |
805 | 813 |
806 if (grouper) | 814 if (grouper) |
807 { | 815 { |
808 bool within_group = Staff_grouper_interface::maybe_pure_within_group (grou per, me, pure, start, end); | 816 bool within_group = Staff_grouper_interface::maybe_pure_within_group (grou per, me, pure, start, end); |
809 if (within_group) | 817 if (within_group) |
810 » return grouper->get_maybe_pure_property ("staff-staff-spacing", pure, st art, end); | 818 return grouper->get_maybe_pure_property ("staff-staff-spacing", pure, st art, end); |
811 else | 819 else |
812 » return grouper->get_maybe_pure_property ("staffgroup-staff-spacing", pur e, start, end); | 820 return grouper->get_maybe_pure_property ("staffgroup-staff-spacing", pur e, start, end); |
813 } | 821 } |
814 return me->get_maybe_pure_property ("default-staff-staff-spacing", pure, start , end); | 822 return me->get_maybe_pure_property ("default-staff-staff-spacing", pure, start , end); |
815 } | 823 } |
816 | 824 |
817 Real | 825 Real |
818 Axis_group_interface::minimum_distance (Grob *g1, Grob *g2, Axis a) | 826 Axis_group_interface::minimum_distance (Grob *g1, Grob *g2, Axis a) |
819 { | 827 { |
820 SCM sym = ly_symbol2scm ((a == Y_AXIS) ? "vertical-skylines" : "horizontal-sky lines"); | 828 SCM sym = ly_symbol2scm ((a == Y_AXIS) ? "vertical-skylines" : "horizontal-sky lines"); |
821 | 829 |
822 Skyline_pair *s1 = Skyline_pair::unsmob (g1->get_property (sym)); | 830 Skyline_pair *s1 = Skyline_pair::unsmob (g1->get_property (sym)); |
823 Skyline_pair *s2 = Skyline_pair::unsmob (g2->get_property (sym)); | 831 Skyline_pair *s2 = Skyline_pair::unsmob (g2->get_property (sym)); |
824 if (s1 && s2) | 832 if (s1 && s2) |
825 return (*s1)[DOWN].distance ((*s2)[UP]); | 833 return (*s1)[DOWN].distance ((*s2)[UP]); |
826 return 0; | 834 return 0; |
827 } | 835 } |
828 | 836 |
829 ADD_INTERFACE (Axis_group_interface, | 837 ADD_INTERFACE (Axis_group_interface, |
830 » "An object that groups other layout objects.", | 838 "An object that groups other layout objects.", |
831 | 839 |
832 » // TODO: some of these properties are specific to | 840 // TODO: some of these properties are specific to |
833 » // VerticalAxisGroup. We should split off a | 841 // VerticalAxisGroup. We should split off a |
834 » // vertical-axis-group-interface. | 842 // vertical-axis-group-interface. |
835 » /* properties */ | 843 /* properties */ |
836 » "adjacent-pure-heights " | 844 "adjacent-pure-heights " |
837 » "axes " | 845 "axes " |
846 » "bound-alignment-interfaces " | |
Neil Puttock
2011/08/14 21:01:24
tab
| |
838 "default-staff-staff-spacing " | 847 "default-staff-staff-spacing " |
Neil Puttock
2011/08/14 21:01:24
tab
| |
839 » "core-interfaces " | 848 "elements " |
840 » "elements " | 849 "max-stretch " |
841 » "max-stretch " | 850 "no-alignment " |
842 » "no-alignment " | 851 "nonstaff-nonstaff-spacing " |
843 » "nonstaff-nonstaff-spacing " | 852 "nonstaff-relatedstaff-spacing " |
844 » "nonstaff-relatedstaff-spacing " | 853 "nonstaff-unrelatedstaff-spacing " |
845 » "nonstaff-unrelatedstaff-spacing " | 854 "pure-relevant-grobs " |
846 » "pure-relevant-grobs " | 855 "pure-relevant-items " |
847 » "pure-relevant-items " | 856 "pure-relevant-spanners " |
848 » "pure-relevant-spanners " | 857 "pure-Y-common " |
849 » "pure-Y-common " | 858 "staff-affinity " |
850 » "staff-affinity " | 859 "staff-grouper " |
851 » "staff-grouper " | 860 "staff-staff-spacing " |
852 » "staff-staff-spacing " | 861 "system-Y-offset " |
853 » "system-Y-offset " | 862 "vertical-skylines " |
854 » "vertical-skylines " | 863 "X-common " |
855 » "X-common " | 864 "Y-common " |
856 » "Y-common " | 865 ); |
857 » ); | |
LEFT | RIGHT |