2 line-interface.cc -- implement Line_interface
4 source file of the GNU LilyPond music typesetter
6 (c) 2004--2007 Han-Wen Nienhuys <hanwen@xs4all.nl>
9 #include "line-interface.hh"
11 #include "staff-symbol-referencer.hh"
13 #include "output-def.hh"
15 #include "font-interface.hh"
18 Line_interface::make_arrow (Offset begin
, Offset end
,
20 Real length
, Real width
)
22 Real angle
= (end
- begin
).arg ();
23 vector
<Offset
> points
;
25 points
.push_back (Offset (0, 0));
26 points
.push_back (Offset (-length
, width
));
27 points
.push_back (Offset (-length
, -width
));
29 for (vsize i
= 0; i
< points
.size (); i
++)
30 points
[i
] = points
[i
] * complex_exp (Offset (0, angle
)) + end
;
32 return Lookup::round_filled_polygon (points
, thick
);
36 Line_interface::make_trill_line (Grob
*me
,
40 Offset dz
= (to
-from
);
41 SCM alist_chain
= Font_interface::text_font_alist_chain (me
);
42 SCM style_alist
= scm_list_n (scm_cons (ly_symbol2scm ("font-encoding"),
43 ly_symbol2scm ("fetaMusic")),
46 Font_metric
*fm
= select_font (me
->layout (),
47 scm_cons (style_alist
,
50 Stencil elt
= fm
->find_by_name ("scripts.trill_element");
51 elt
.align_to (Y_AXIS
, CENTER
);
52 Real elt_len
= elt
.extent (X_AXIS
).length ();
55 programming_error ("can't find scripts.trill_element");
63 line
.add_at_edge (X_AXIS
, RIGHT
, elt
, 0);
64 len
= line
.extent (X_AXIS
).length ();
66 while (len
+ elt_len
< dz
.length ());
68 line
.rotate (dz
.arg (), Offset (LEFT
, CENTER
));
69 line
.translate (from
);
76 Line_interface::make_zigzag_line (Grob
*me
,
82 Real thick
= Staff_symbol_referencer::line_thickness (me
);
83 thick
*= robust_scm2double (me
->get_property ("thickness"), 1.0); // todo: staff sym referencer?
85 Real staff_space
= Staff_symbol_referencer::staff_space (me
);
87 Real w
= robust_scm2double (me
->get_property ("zigzag-width"), 1) * staff_space
;
88 int count
= (int) ceil (dz
.length () / w
);
89 w
= dz
.length () / count
;
91 Real l
= robust_scm2double (me
->get_property ("zigzag-length"), 1) * w
;
92 Real h
= l
> w
/ 2 ? sqrt (l
* l
- w
* w
/ 4) : 0;
94 Offset rotation_factor
= complex_exp (Offset (0, dz
.arg ()));
97 points
[0] = Offset (0, -h
/ 2);
98 points
[1] = Offset (w
/ 2, h
/ 2);
99 points
[2] = Offset (w
, -h
/ 2);
100 for (int i
= 0; i
< 3; i
++)
101 points
[i
] = complex_multiply (points
[i
], rotation_factor
);
103 Stencil
squiggle (Line_interface::make_line (thick
, points
[0], points
[1]));
104 squiggle
.add_stencil (Line_interface::make_line (thick
, points
[1], points
[2]));
107 for (int i
= 0; i
< count
; i
++)
109 Stencil
moved_squiggle (squiggle
);
110 moved_squiggle
.translate (from
+ Offset (i
* w
, 0) * rotation_factor
);
111 total
.add_stencil (moved_squiggle
);
115 b
.add_point (Offset (0, 0));
117 b
[X_AXIS
].widen (thick
/ 2);
118 b
[Y_AXIS
].widen (thick
/ 2);
120 return Stencil (b
, total
.expr ());
125 Line_interface::make_dashed_line (Real thick
, Offset from
, Offset to
,
126 Real dash_period
, Real dash_fraction
)
128 dash_fraction
= min (max (dash_fraction
, 0.0), 1.0);
129 Real on
= dash_fraction
* dash_period
+ thick
;
130 Real off
= max (0.0, dash_period
- on
);
132 SCM at
= scm_list_n (ly_symbol2scm ("dashed-line"),
133 scm_from_double (thick
),
134 scm_from_double (on
),
135 scm_from_double (off
),
136 scm_from_double (to
[X_AXIS
] - from
[X_AXIS
]),
137 scm_from_double (to
[Y_AXIS
] - from
[Y_AXIS
]),
138 scm_from_double (0.0),
142 box
.add_point (Offset (0, 0));
143 box
.add_point (to
- from
);
145 box
[X_AXIS
].widen (thick
/ 2);
146 box
[Y_AXIS
].widen (thick
/ 2);
148 Stencil m
= Stencil (box
, at
);
154 Line_interface::make_line (Real th
, Offset from
, Offset to
)
156 SCM at
= scm_list_n (ly_symbol2scm ("draw-line"),
157 scm_from_double (th
),
158 scm_from_double (from
[X_AXIS
]),
159 scm_from_double (from
[Y_AXIS
]),
160 scm_from_double (to
[X_AXIS
]),
161 scm_from_double (to
[Y_AXIS
]),
165 box
.add_point (from
);
168 box
[X_AXIS
].widen (th
/ 2);
169 box
[Y_AXIS
].widen (th
/ 2);
171 return Stencil (box
, at
);
175 Line_interface::arrows (Grob
*me
, Offset from
, Offset to
,
180 if (from_arrow
|| to_arrow
)
182 Real thick
= Staff_symbol_referencer::line_thickness (me
)
183 * robust_scm2double (me
->get_property ("thickness"), 1);
184 Real ss
= Staff_symbol_referencer::staff_space (me
);
186 Real len
= robust_scm2double (me
->get_property ("arrow-length"), 1.3 * ss
);
187 Real wid
= robust_scm2double (me
->get_property ("arrow-width"), 0.5 * ss
);
190 a
.add_stencil (make_arrow (from
, to
, thick
, len
, wid
));
193 a
.add_stencil (make_arrow (to
, from
, thick
, len
, wid
));
200 Line_interface::line (Grob
*me
, Offset from
, Offset to
)
202 Real thick
= Staff_symbol_referencer::line_thickness (me
)
203 * robust_scm2double (me
->get_property ("thickness"), 1);
205 SCM type
= me
->get_property ("style");
206 if (type
== ly_symbol2scm ("zigzag"))
208 return make_zigzag_line (me
, from
, to
);
210 else if (type
== ly_symbol2scm ("trill"))
211 return make_trill_line (me
, from
, to
);
215 if (type
== ly_symbol2scm ("dashed-line") || type
== ly_symbol2scm ("dotted-line"))
219 = type
== ly_symbol2scm ("dotted-line")
221 : robust_scm2double (me
->get_property ("dash-fraction"), 0.4);
223 fraction
= min (max (fraction
, 0.0), 1.0);
224 Real period
= Staff_symbol_referencer::staff_space (me
)
225 * robust_scm2double (me
->get_property ("dash-period"), 1.0);
230 Real len
= (to
-from
).length ();
232 int n
= (int) rint ((len
- period
* fraction
) / period
);
237 TODO: figure out something intelligent for really short
240 period
= ((to
-from
).length () - period
* fraction
) / n
;
242 stencil
= make_dashed_line (thick
, from
, to
, period
, fraction
);
245 stencil
= make_line (thick
, from
, to
);
250 ADD_INTERFACE (Line_interface
,
251 "Generic line objects. Any object using lines supports this."
252 " The property @code{style} can be @code{line},"
253 " @code{dashed-line}, @code{trill}, @code{dotted-line} or"
256 "For @code{dashed-line}, the length of the dashes is tuned"
257 " with @code{dash-fraction}. If the latter is set to@tie{}0, a"
258 " dotted line is produced. If @code{dash-period} is negative,"
259 " the line is made transparent.",