source file of the GNU LilyPond music typesetter
- (c) 2000--2007 Han-Wen Nienhuys <hanwen@xs4all.nl>
+ (c) 2000--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
*/
#include "axis-group-interface.hh"
#include "paper-column.hh"
#include "paper-score.hh"
#include "separation-item.hh"
+#include "skyline-pair.hh"
#include "stencil.hh"
#include "system.hh"
#include "warn.hh"
return common;
}
-MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_x_common, 1);
SCM
-Axis_group_interface::calc_x_common (SCM grob)
+Axis_group_interface::calc_common (Grob *me, Axis axis)
{
- Grob *me = unsmob_grob (grob);
-
extract_grob_set (me, "elements", elts);
- Grob *common = common_refpoint_of_array (elts, me, X_AXIS);
+ Grob *common = common_refpoint_of_array (elts, me, axis);
+ if (!common)
+ {
+ me->programming_error ("No common parent found in calc_common axis.");
+ return SCM_EOL;
+ }
+
return common->self_scm ();
}
+
+MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_x_common, 1);
+SCM
+Axis_group_interface::calc_x_common (SCM grob)
+{
+ return calc_common (unsmob_grob (grob), X_AXIS);
+}
+
MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_y_common, 1);
SCM
Axis_group_interface::calc_y_common (SCM grob)
{
- Grob *me = unsmob_grob (grob);
-
- extract_grob_set (me, "elements", elts);
- Grob *common = common_refpoint_of_array (elts, me, Y_AXIS);
- return common->self_scm ();
+ return calc_common (unsmob_grob (grob), Y_AXIS);
}
Interval
}
}
+// TODO: it is tricky to correctly handle skyline placement of cross-staff grobs.
+// For example, cross-staff beams cannot be formatted until the distance between
+// staves is known and therefore any grobs that depend on the beam cannot be placed
+// until the skylines are known. On the other hand, the distance between staves should
+// really depend on position of the cross-staff grobs that lie between them.
+// Currently, we just leave cross-staff grobs out of the
+// skyline altogether, but this could mean that staves are placed so close together
+// that there is no room for the cross-staff grob. It also means, of course, that
+// we don't get the benefits of skyline placement for cross-staff grobs.
Skyline_pair
Axis_group_interface::skyline_spacing (Grob *me, vector<Grob*> elements)
{
+ /* For grobs with an outside-staff-priority, the sorting function might
+ call extent and cause suicide. This breaks the contract that is required
+ for the STL sort function. To avoid this, we make sure that any suicides
+ are triggered beforehand.
+ */
+ for (vsize i = 0; i < elements.size (); i++)
+ if (scm_is_number (elements[i]->get_property ("outside-staff-priority")))
+ elements[i]->extent (elements[i], X_AXIS);
+
vector_sort (elements, staff_priority_less);
Grob *x_common = common_refpoint_of_array (elements, me, X_AXIS);
Grob *y_common = common_refpoint_of_array (elements, me, Y_AXIS);
Skyline_pair skylines;
for (i = 0; i < elements.size ()
&& !scm_is_number (elements[i]->get_property ("outside-staff-priority")); i++)
- add_boxes (elements[i], x_common, y_common, &boxes, &skylines);
+ if (!to_boolean (elements[i]->get_property ("cross-staff")))
+ add_boxes (elements[i], x_common, y_common, &boxes, &skylines);
SCM padding_scm = me->get_property ("skyline-horizontal-padding");
Real padding = robust_scm2double (padding_scm, 0.1);
skylines.merge (Skyline_pair (boxes, padding, X_AXIS));
for (; i < elements.size (); i++)
{
+ if (to_boolean (elements[i]->get_property ("cross-staff")))
+ continue;
+
SCM priority = elements[i]->get_property ("outside-staff-priority");
vector<Grob*> current_elts;
current_elts.push_back (elements[i]);
return scm_from_double (ret);
}
-extern bool debug_skylines;
MAKE_SCHEME_CALLBACK (Axis_group_interface, print, 1)
SCM
Axis_group_interface::print (SCM smob)
Stencil ret;
if (Skyline_pair *s = Skyline_pair::unsmob (me->get_property ("vertical-skylines")))
{
- ret.add_stencil (Lookup::points_to_line_stencil (0.1, (*s)[UP].to_points (X_AXIS)).in_color (255, 0, 255));
- ret.add_stencil (Lookup::points_to_line_stencil (0.1, (*s)[DOWN].to_points (X_AXIS)).in_color (0, 255, 255));
+ ret.add_stencil (Lookup::points_to_line_stencil (0.1, (*s)[UP].to_points (X_AXIS))
+ .in_color (255, 0, 255));
+ ret.add_stencil (Lookup::points_to_line_stencil (0.1, (*s)[DOWN].to_points (X_AXIS))
+ .in_color (0, 255, 255));
}
return ret.smobbed_copy ();
}