+ Spanner *orig = dynamic_cast<Spanner *> (me->original ());
+
+ orig = orig ? orig : me;
+
+ if (orig->is_broken ())
+ {
+ Real total_width = 0.0;
+ vector<Real> span_data;
+
+ if (!orig->is_broken ())
+ span_data.push_back (orig->spanner_length ());
+ else
+ for (vsize i = 0; i < orig->broken_intos_.size (); i++)
+ span_data.push_back (orig->broken_intos_[i]->spanner_length ());
+
+ vector<Interval> unnormalized_endpoints;
+
+ for (vsize i = 0; i < span_data.size (); i++)
+ {
+ unnormalized_endpoints.push_back (Interval (total_width, total_width + span_data[i]));
+ total_width += span_data[i];
+ }
+
+ for (vsize i = 0; i < unnormalized_endpoints.size (); i++)
+ {
+ SCM t = ly_interval2scm (1 / total_width * unnormalized_endpoints[i]);
+ orig->broken_intos_[i]->set_property ("normalized-endpoints", t);
+ if (me->get_break_index () == i)
+ result = t;
+ }
+ }
+ else
+ {
+ result = scm_cons (scm_from_double (0.0), scm_from_double (1.0));
+ orig->set_property ("normalized-endpoints", result);
+ }
+
+ return result;
+}
+
+Spanner *
+unsmob_spanner (SCM s)
+{
+ return dynamic_cast<Spanner *> (unsmob_grob (s));
+}
+
+MAKE_SCHEME_CALLBACK (Spanner, bounds_width, 1);
+SCM
+Spanner::bounds_width (SCM grob)
+{
+ Spanner *me = unsmob_spanner (grob);
+
+ Grob *common = me->get_bound (LEFT)->common_refpoint (me->get_bound (RIGHT), X_AXIS);
+
+ Interval w (me->get_bound (LEFT)->relative_coordinate (common, X_AXIS),
+ me->get_bound (RIGHT)->relative_coordinate (common, X_AXIS));
+
+ w -= me->relative_coordinate (common, X_AXIS);
+
+ return ly_interval2scm (w);
+}
+
+MAKE_SCHEME_CALLBACK (Spanner, kill_zero_spanned_time, 1);
+SCM
+Spanner::kill_zero_spanned_time (SCM grob)
+{
+ Spanner *me = unsmob_spanner (grob);
+ /*
+ Remove the line or hairpin at the start of the line. For
+ piano voice indicators, it makes no sense to have them at
+ the start of the line.
+
+ I'm not sure what the official rules for glissandi are, but
+ usually the 2nd note of the glissando is "exact", so when playing
+ from the start of the line, there is no need to glide.
+
+ From a typographical p.o.v. this makes sense, since the amount of
+ space left of a note at the start of a line is very small.
+
+ --hwn.
+
+ */
+ if (me->get_bound (LEFT)->break_status_dir ())
+ {
+ Interval_t<Moment> moments = me->spanned_time ();
+ moments [LEFT].grace_part_ = 0;
+ if (moments.length () == Moment (0, 0))
+ me->suicide ();
+ }