2 line-spanner.cc -- implement Line_spanner
4 source file of the GNU LilyPond music typesetter
6 (c) 2000--2001 Jan Nieuwenhuizen <janneke@gnu.org>
12 #include "line-spanner.hh"
13 #include "paper-def.hh"
14 #include "paper-column.hh"
15 #include "staff-symbol-referencer.hh"
20 Line_spanner::line_atom (Grob
* me
, Real dx
, Real dy
)
23 SCM type
= me
->get_grob_property ("type");
24 if (gh_symbol_p (type
)
25 && (type
== ly_symbol2scm ("line")
26 || type
== ly_symbol2scm ("dashed-line")
27 || type
== ly_symbol2scm ("dotted-line")))
29 Real staff_space
= Staff_symbol_referencer::staff_space (me
);
30 Real thick
= me
->paper_l ()->get_var ("stafflinethickness");
32 SCM s
= me
->get_grob_property ("line-thickness");
34 thick
*= gh_scm2double (s
);
36 // maybe these should be in line-thickness?
37 Real length
= staff_space
;
38 s
= me
->get_grob_property ("dash-length");
40 length
= gh_scm2double (s
) * staff_space
;
42 Real period
= 2 * length
+ thick
;
43 s
= me
->get_grob_property ("dash-period");
45 period
= gh_scm2double (s
) * staff_space
;
47 if (type
== ly_symbol2scm ("dotted-line"))
50 if (type
== ly_symbol2scm ("line"))
51 length
= period
+ thick
;
53 Real on
= length
- thick
;
54 Real off
= period
- on
;
56 list
= gh_list (ly_symbol2scm ("dashed-line"),
57 gh_double2scm (thick
),
68 Line_spanner::get_broken_offset (Grob
*me
, Direction dir
)
70 Spanner
*spanner
= dynamic_cast<Spanner
*> (me
);
71 Item
* bound
= spanner
->get_bound (dir
);
73 if (!bound
->break_status_dir ())
76 bound
->common_refpoint (Staff_symbol_referencer::staff_symbol_l (me
),
78 bound
->common_refpoint (Staff_symbol_referencer::staff_symbol_l (me
),
82 return Offset (abs (bound
->extent (common
[X_AXIS
], X_AXIS
)[-dir
]),
83 bound
->extent (common
[Y_AXIS
], Y_AXIS
).center ());
89 Line_spanner::broken_trend_offset (Grob
*me
, Direction dir
)
91 /* A broken line-spaner should maintain the same vertical trend
92 the unbroken line-spanner would have had.
95 if (Spanner
*mother
= dynamic_cast<Spanner
*> (me
->original_l_
))
97 for (int i
= dir
== LEFT
? 0 : mother
->broken_into_l_arr_
.size () - 1;
98 dir
== LEFT
? i
< mother
->broken_into_l_arr_
.size () : i
> 0;
99 dir
== LEFT
? i
++ : i
--)
101 if (mother
->broken_into_l_arr_
[i
- dir
] == me
)
103 Grob
*neighbour
= mother
->broken_into_l_arr_
[i
];
104 Offset neighbour_o
= get_broken_offset (neighbour
, dir
);
105 Offset me_o
= get_broken_offset (me
, -dir
);
106 // Hmm, why not return me_o[X], but recalc in brew_mol?
108 (neighbour_o
[Y_AXIS
]*me_o
[X_AXIS
]
109 - me_o
[Y_AXIS
]*neighbour_o
[X_AXIS
]) * dir
/
110 (me_o
[X_AXIS
] + neighbour_o
[X_AXIS
]));
120 Warning: this thing is a cross-staff object, so it should have empty Y-dimensions.
122 (If not, you risk that this is called from the staff-alignment
123 routine, via molecule_extent. At this point, the staffs aren't
124 separated yet, so it doesn't work cross-staff.
128 MAKE_SCHEME_CALLBACK (Line_spanner
, brew_molecule
, 1);
130 Line_spanner::brew_molecule (SCM smob
)
132 Grob
*me
= unsmob_grob (smob
);
134 Spanner
*spanner
= dynamic_cast<Spanner
*> (me
);
135 Item
* bound_drul
[] = {
136 spanner
->get_bound (LEFT
),
138 spanner
->get_bound (RIGHT
)
141 Item
** bound
= bound_drul
+ 1;
143 Grob
*common
[] = { 0, 0 };
144 for (Axis a
= X_AXIS
; a
< NO_AXES
; a
= Axis (a
+ 1))
146 common
[a
] = bound
[LEFT
]->common_refpoint (bound
[RIGHT
], a
);
152 Real gap
= gh_scm2double (me
->get_grob_property ("gap"));
153 Real dist
; /*distance between points */
155 Offset
ofxy (gap
, 0); /*offset from start point to start of line*/
161 if (bound
[LEFT
]->break_status_dir () || bound
[RIGHT
]->break_status_dir ())
162 /* across line break */
164 Direction broken
= bound
[LEFT
]->break_status_dir () ? LEFT
: RIGHT
;
166 dxy
[X_AXIS
] = bound
[RIGHT
]->extent (common
[X_AXIS
], X_AXIS
)[LEFT
]
167 - bound
[LEFT
]->extent (common
[X_AXIS
], X_AXIS
)[RIGHT
];
169 dxy
+= broken_trend_offset (me
, broken
);
170 dxy
[X_AXIS
] -= 1 * gap
;
173 me
->relative_coordinate (common
[Y_AXIS
], Y_AXIS
));
176 bound
[-broken
]->relative_coordinate (common
[Y_AXIS
],
181 my_off
[Y_AXIS
] += dxy
[Y_AXIS
];
186 Real off
= gap
+ ((bound
[LEFT
]->extent (bound
[LEFT
], X_AXIS
).length ()*3)/4); // distance from center to start of line
187 dxy
[X_AXIS
] = bound
[RIGHT
]->extent (common
[X_AXIS
], X_AXIS
).center ()
188 - bound
[LEFT
]->extent (common
[X_AXIS
], X_AXIS
).center ();
189 dxy
[Y_AXIS
] = bound
[RIGHT
]->extent (common
[Y_AXIS
], Y_AXIS
).center ()
190 - bound
[LEFT
]->extent (common
[Y_AXIS
], Y_AXIS
).center ();
192 dist
= sqrt (dxy
[X_AXIS
]*dxy
[X_AXIS
]+dxy
[Y_AXIS
]*dxy
[Y_AXIS
]);
193 ofxy
= dxy
* (off
/dist
);
196 my_off
= Offset (me
->relative_coordinate (common
[X_AXIS
], X_AXIS
),
197 me
->relative_coordinate (common
[Y_AXIS
], Y_AXIS
));
199 his_off
= Offset (bound
[LEFT
]->relative_coordinate (common
[X_AXIS
],
201 bound
[LEFT
]->relative_coordinate (common
[Y_AXIS
],
206 SCM list
= Line_spanner::line_atom (me
, dxy
[X_AXIS
], dxy
[Y_AXIS
]);
211 Box
b (Interval (0, dxy
[X_AXIS
]), Interval (0, dxy
[Y_AXIS
]));
213 line
= Molecule (b
, list
);
214 line
.translate_axis (bound
[LEFT
]->extent (bound
[LEFT
], X_AXIS
).length ()/2, X_AXIS
);
217 line
.translate (ofxy
- my_off
+ his_off
);
219 return line
.smobbed_copy ();