2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 2004--2011 Han-Wen Nienhuys <hanwen@xs4all.nl>
6 LilyPond is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 LilyPond is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
20 #include "line-interface.hh"
22 #include "font-interface.hh"
25 #include "output-def.hh"
26 #include "staff-symbol-referencer.hh"
29 Line_interface::make_arrow (Offset begin
, Offset end
,
31 Real length
, Real width
)
33 Real angle
= (end
- begin
).arg ();
34 vector
<Offset
> points
;
36 points
.push_back (Offset (0, 0));
37 points
.push_back (Offset (-length
, width
));
38 points
.push_back (Offset (-length
, -width
));
40 for (vsize i
= 0; i
< points
.size (); i
++)
41 points
[i
] = points
[i
] * complex_exp (Offset (0, angle
)) + end
;
43 return Lookup::round_filled_polygon (points
, thick
);
47 Line_interface::make_trill_line (Grob
*me
,
51 Offset dz
= (to
- from
);
53 Font_metric
*fm
= Font_interface::get_default_font (me
);
55 Stencil elt
= fm
->find_by_name ("scripts.trill_element");
56 elt
.align_to (Y_AXIS
, CENTER
);
57 Real elt_len
= elt
.extent (X_AXIS
).length ();
60 programming_error ("can't find scripts.trill_element");
68 line
.add_at_edge (X_AXIS
, RIGHT
, elt
, 0);
69 len
= line
.extent (X_AXIS
).length ();
71 while (len
+ elt_len
< dz
.length ());
73 line
.rotate (dz
.arg (), Offset (LEFT
, CENTER
));
74 line
.translate (from
);
81 Line_interface::make_zigzag_line (Grob
*me
,
85 Offset dz
= to
- from
;
87 Real thick
= Staff_symbol_referencer::line_thickness (me
);
88 thick
*= robust_scm2double (me
->get_property ("thickness"), 1.0); // todo: staff sym referencer?
90 Real staff_space
= Staff_symbol_referencer::staff_space (me
);
92 Real w
= robust_scm2double (me
->get_property ("zigzag-width"), 1) * staff_space
;
93 int count
= (int) ceil (dz
.length () / w
);
94 w
= dz
.length () / count
;
96 Real l
= robust_scm2double (me
->get_property ("zigzag-length"), 1) * w
;
97 Real h
= l
> w
/ 2 ? sqrt (l
* l
- w
* w
/ 4) : 0;
99 Offset rotation_factor
= complex_exp (Offset (0, dz
.arg ()));
102 points
[0] = Offset (0, -h
/ 2);
103 points
[1] = Offset (w
/ 2, h
/ 2);
104 points
[2] = Offset (w
, -h
/ 2);
105 for (int i
= 0; i
< 3; i
++)
106 points
[i
] = complex_multiply (points
[i
], rotation_factor
);
108 Stencil
squiggle (Line_interface::make_line (thick
, points
[0], points
[1]));
109 squiggle
.add_stencil (Line_interface::make_line (thick
, points
[1], points
[2]));
112 for (int i
= 0; i
< count
; i
++)
114 Stencil
moved_squiggle (squiggle
);
115 moved_squiggle
.translate (from
+ Offset (i
* w
, 0) * rotation_factor
);
116 total
.add_stencil (moved_squiggle
);
124 Line_interface::make_dashed_line (Real thick
, Offset from
, Offset to
,
125 Real dash_period
, Real dash_fraction
)
127 dash_fraction
= min (max (dash_fraction
, 0.0), 1.0);
128 Real on
= dash_fraction
* dash_period
+ thick
;
129 Real off
= max (0.0, dash_period
- on
);
131 SCM at
= scm_list_n (ly_symbol2scm ("dashed-line"),
132 scm_from_double (thick
),
133 scm_from_double (on
),
134 scm_from_double (off
),
135 scm_from_double (to
[X_AXIS
] - from
[X_AXIS
]),
136 scm_from_double (to
[Y_AXIS
] - from
[Y_AXIS
]),
137 scm_from_double (0.0),
141 box
.add_point (Offset (0, 0));
142 box
.add_point (to
- from
);
144 box
[X_AXIS
].widen (thick
/ 2);
145 box
[Y_AXIS
].widen (thick
/ 2);
147 Stencil m
= Stencil (box
, at
);
153 Line_interface::make_line (Real th
, Offset from
, Offset to
)
155 SCM at
= scm_list_n (ly_symbol2scm ("draw-line"),
156 scm_from_double (th
),
157 scm_from_double (from
[X_AXIS
]),
158 scm_from_double (from
[Y_AXIS
]),
159 scm_from_double (to
[X_AXIS
]),
160 scm_from_double (to
[Y_AXIS
]),
164 box
.add_point (from
);
167 box
[X_AXIS
].widen (th
/ 2);
168 box
[Y_AXIS
].widen (th
/ 2);
170 return Stencil (box
, at
);
174 Line_interface::arrows (Grob
*me
, Offset from
, Offset to
,
179 if (from_arrow
|| to_arrow
)
181 Real thick
= Staff_symbol_referencer::line_thickness (me
)
182 * robust_scm2double (me
->get_property ("thickness"), 1);
183 Real ss
= Staff_symbol_referencer::staff_space (me
);
185 Real len
= robust_scm2double (me
->get_property ("arrow-length"), 1.3 * ss
);
186 Real wid
= robust_scm2double (me
->get_property ("arrow-width"), 0.5 * ss
);
189 a
.add_stencil (make_arrow (from
, to
, thick
, len
, wid
));
192 a
.add_stencil (make_arrow (to
, from
, thick
, len
, wid
));
199 Line_interface::line (Grob
*me
, Offset from
, Offset to
)
201 Real thick
= Staff_symbol_referencer::line_thickness (me
)
202 * robust_scm2double (me
->get_property ("thickness"), 1);
204 SCM type
= me
->get_property ("style");
205 if (type
== ly_symbol2scm ("zigzag"))
206 return make_zigzag_line (me
, from
, to
);
207 else if (type
== ly_symbol2scm ("trill"))
208 return make_trill_line (me
, from
, to
);
209 else if (type
== ly_symbol2scm ("none"))
214 if (type
== ly_symbol2scm ("dashed-line") || type
== ly_symbol2scm ("dotted-line"))
218 = type
== ly_symbol2scm ("dotted-line")
220 : robust_scm2double (me
->get_property ("dash-fraction"), 0.4);
222 fraction
= min (max (fraction
, 0.0), 1.0);
223 Real period
= Staff_symbol_referencer::staff_space (me
)
224 * robust_scm2double (me
->get_property ("dash-period"), 1.0);
229 Real len
= (to
- from
).length ();
231 int n
= (int) rint ((len
- period
* fraction
) / period
);
236 TODO: figure out something intelligent for really short
239 period
= ((to
- from
).length () - period
* fraction
) / n
;
241 stencil
= make_dashed_line (thick
, from
, to
, period
, fraction
);
244 stencil
= make_line (thick
, from
, to
);
249 ADD_INTERFACE (Line_interface
,
250 "Generic line objects. Any object using lines supports this."
251 " The property @code{style} can be @code{line},"
252 " @code{dashed-line}, @code{trill}, @code{dotted-line},"
253 " @code{zigzag} or @code{none} (a transparent line).\n"
255 "For @code{dashed-line}, the length of the dashes is tuned"
256 " with @code{dash-fraction}. If the latter is set to@tie{}0, a"
257 " dotted line is produced.",