- Grob *me= unsmob_grob (smob);
- Spanner *spanner = dynamic_cast<Spanner*> (me);
-
- Grob *common[] = { 0, 0 };
- common[X_AXIS] = spanner->get_bound (LEFT)->common_refpoint (spanner->get_bound (RIGHT), X_AXIS);
- common[Y_AXIS] = spanner->get_bound (LEFT)->common_refpoint (spanner->get_bound (RIGHT), Y_AXIS);
-
- if (!common[X_AXIS] || !common[Y_AXIS])
- return SCM_EOL;
-
- Real dx =
- spanner->get_bound (LEFT)->relative_coordinate (common[X_AXIS], X_AXIS)
- - spanner->get_bound (RIGHT)->relative_coordinate (common[X_AXIS], X_AXIS)
- + spanner->get_bound (RIGHT)->extent (spanner->get_bound (RIGHT),
- X_AXIS)[LEFT]
- - spanner->get_bound (LEFT)->extent (spanner->get_bound (LEFT),
- X_AXIS)[RIGHT];
-
- Real dy =
- spanner->get_bound (LEFT)->relative_coordinate (common[Y_AXIS], Y_AXIS)
- - spanner->get_bound (RIGHT)->relative_coordinate (common[Y_AXIS], Y_AXIS)
- + spanner->get_bound (RIGHT)->extent (spanner->get_bound (RIGHT),
- Y_AXIS).center ()
- - spanner->get_bound (LEFT)->extent (spanner->get_bound (LEFT),
- Y_AXIS).center ();
-
- Molecule line;
- Real gap = gh_scm2double (me->get_grob_property ("gap"));
- Offset o (dx, dy);
- o *= (o.length () - 2 * gap) / o.length ();
-
- SCM list = Line_spanner::line_atom (me, o[X_AXIS], o[Y_AXIS]);
-
- if (list == SCM_EOL)
- return SCM_EOL;
-
- Box b (Interval (0, o[X_AXIS]), Interval (0, o[Y_AXIS]));
-
- line = Molecule (b, list);
- line.translate_axis (spanner->get_bound (LEFT)->extent (spanner->get_bound (LEFT), X_AXIS).length (), X_AXIS);
- Offset g = o * (gap / o.length ());
- line.translate (g);
-
- return line.smobbed_copy ();
+ Spanner *me = dynamic_cast<Spanner *> (unsmob_grob (smob));
+
+ Drul_array<Item *> bound (me->get_bound (LEFT),
+ me->get_bound (RIGHT));
+
+ Real gap = robust_scm2double (me->get_property ("gap"), 0.0);
+
+ Offset ofxy (gap, 0); /* offset from start point to start of line */
+ Offset dxy;
+ Offset my_off;
+ Offset his_off;
+
+ if (bound[RIGHT]->break_status_dir ())
+ {
+ if (bound[LEFT]->break_status_dir ())
+ {
+ programming_error ("line-spanner with two broken ends. Farewell sweet world.");
+
+ me->suicide ();
+ return SCM_EOL;
+ }
+
+ /*
+ This is hairy. For the normal case, we simply find common
+ parents, and draw a line between the bounds. When two note
+ heads are on different systems, there is no common parent
+ anymore. We have to find the piano-staff object.
+ */
+
+ int k = broken_spanner_index (me);
+ Spanner *parent_sp = dynamic_cast<Spanner *> (me->original ());
+ Spanner *next_sp = parent_sp->broken_intos_ [k + 1];
+ Item *next_bound = next_sp->get_bound (RIGHT);
+
+ if (next_bound->break_status_dir ())
+ {
+ programming_error ("no note heads for the line spanner on next line?"
+ " Confused.");
+ me->suicide ();
+ return SCM_EOL;
+ }
+
+ Grob *commonx = bound[LEFT]->common_refpoint (bound[RIGHT], X_AXIS);
+ commonx = me->common_refpoint (commonx, X_AXIS);
+
+ Grob *next_common_y = line_spanner_common_parent (next_bound);
+ Grob *this_common_y = line_spanner_common_parent (bound[LEFT]);
+
+ Grob *all_common_y = me->common_refpoint (this_common_y, Y_AXIS);
+
+ Interval next_ext = next_bound->extent (next_common_y, Y_AXIS);
+ Interval this_ext = bound[LEFT]->extent (this_common_y, Y_AXIS);
+
+ Real yoff = this_common_y->relative_coordinate (all_common_y, Y_AXIS);
+
+ Offset p1 (bound[LEFT]->extent (commonx, X_AXIS)[RIGHT],
+ this_ext.center () + yoff);
+ Offset p2 (bound[RIGHT]->extent (commonx, X_AXIS)[LEFT],
+ next_ext.center () + yoff);
+
+ Offset dz (p2 -p1);
+ Real len = dz.length ();
+
+ Offset dir = dz * (1 / len);
+ dz = (dz.length () - 2 * gap) * dir;
+
+ Stencil l (line_stencil (me, Offset (0, 0), dz));
+
+ l.translate (dir * gap + p1
+ - Offset (me->relative_coordinate (commonx, X_AXIS),
+ me->relative_coordinate (all_common_y, Y_AXIS)));
+
+ return l.smobbed_copy ();
+ }
+ else
+ {
+ Grob *common[] = { me, me };
+ for (int a = X_AXIS; a < NO_AXES; a++)
+ {
+ common[a] = me->common_refpoint (bound[RIGHT], Axis (a));
+ common[a] = common[a]->common_refpoint (bound[LEFT], Axis (a));
+ }
+
+ // distance from center to start of line
+ Real off = gap + ((bound[LEFT]->extent (bound[LEFT], X_AXIS).length () * 3) / 4);
+
+ for (int a = X_AXIS; a < NO_AXES; a++)
+ {
+ Axis ax = (Axis)a;
+ dxy[ax]
+ = + robust_relative_extent (bound[RIGHT], common[X_AXIS], ax).center ()
+ - robust_relative_extent (bound[LEFT], common[X_AXIS], ax).center ();
+
+ my_off[ax] = me->relative_coordinate (common[a], ax);
+ his_off[ax] = bound[LEFT]->relative_coordinate (common[a], ax);
+ }
+
+ ofxy = dxy * (off / dxy.length ());
+ dxy -= 2*ofxy;
+
+ Stencil line = line_stencil (me, Offset (0, 0), dxy);
+
+ line.translate_axis (bound[LEFT]->extent (bound[LEFT], X_AXIS).length () / 2, X_AXIS);
+ line.translate (ofxy - my_off + his_off);
+ return line.smobbed_copy ();
+ }