]> git.donarmstrong.com Git - lilypond.git/blob - lily/line-interface.cc
move zigzag to line-interface.
[lilypond.git] / lily / line-interface.cc
1 /*
2   line-interface.cc -- implement Line_interface
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 2004--2007 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 */
8
9 #include "line-interface.hh"
10
11 #include "staff-symbol-referencer.hh"
12 #include "lookup.hh"
13 #include "output-def.hh"
14 #include "grob.hh"
15
16 Stencil
17 Line_interface::make_arrow (Offset begin, Offset end,
18                             Real thick,
19                             Real length, Real width)
20 {
21   Real angle = (end - begin).arg ();
22   vector<Offset> points;
23
24   points.push_back (Offset (0, 0));
25   points.push_back (Offset (-length, width));
26   points.push_back (Offset (-length, -width));
27
28   for (vsize i = 0; i < points.size (); i++)
29     points[i] = points[i] * complex_exp (Offset (0, angle)) + end;
30
31   return Lookup::round_filled_polygon (points, thick);
32 }
33
34 Stencil
35 Line_interface::zigzag_stencil (Grob *me,
36                                 Offset from,
37                                 Offset to)
38 {
39   Offset dz = to -from;
40
41   Real thick = Staff_symbol_referencer::line_thickness (me);
42   thick *= robust_scm2double (me->get_property ("thickness"), 1.0); // todo: staff sym referencer? 
43
44   Real staff_space = Staff_symbol_referencer::staff_space (me);
45
46   Real w = robust_scm2double (me->get_property ("zigzag-width"), 1) * staff_space;
47   int count = (int) ceil (dz.length () / w);
48   w = dz.length () / count;
49
50   Real l = robust_scm2double (me->get_property ("zigzag-length"), 1) * w;
51   Real h = l > w / 2 ? sqrt (l * l - w * w / 4) : 0;
52
53   Offset rotation_factor = complex_exp (Offset (0, dz.arg ()));
54
55   Offset points[3];
56   points[0] = Offset (0, -h / 2);
57   points[1] = Offset (w / 2, h / 2);
58   points[2] = Offset (w, -h / 2);
59   for (int i = 0; i < 3; i++)
60     points[i] = complex_multiply (points[i], rotation_factor);
61
62   Stencil squiggle (Line_interface::make_line (thick, points[0], points[1]));
63   squiggle.add_stencil (Line_interface::make_line (thick, points[1], points[2]));
64
65   Stencil total;
66   for (int i = 0; i < count; i++)
67     {
68       Stencil moved_squiggle (squiggle);
69       moved_squiggle.translate (from + Offset (i * w, 0) * rotation_factor);
70       total.add_stencil (moved_squiggle);
71     }
72
73   Box b;
74   b.add_point (Offset (0, 0));
75   b.add_point (dz);
76   b[X_AXIS].widen (thick / 2);
77   b[Y_AXIS].widen (thick / 2);
78
79   return Stencil (b, total.expr ());
80 }
81
82
83 Stencil
84 Line_interface::make_dashed_line (Real thick, Offset from, Offset to,
85                                   Real dash_period, Real dash_fraction)
86 {
87   dash_fraction = min (max (dash_fraction, 0.0), 1.0);
88   Real on = dash_fraction * dash_period + thick;
89   Real off = dash_period - on;
90
91   SCM at = scm_list_n (ly_symbol2scm ("dashed-line"),
92                        scm_from_double (thick),
93                        scm_from_double (on),
94                        scm_from_double (off),
95                        scm_from_double (to[X_AXIS] - from[X_AXIS]),
96                        scm_from_double (to[Y_AXIS] - from[Y_AXIS]),
97                        scm_from_double (0.0),
98                        SCM_UNDEFINED);
99
100   Box box;
101   box.add_point (Offset (0, 0));
102   box.add_point (to - from);
103
104   box[X_AXIS].widen (thick / 2);
105   box[Y_AXIS].widen (thick / 2);
106
107   Stencil m = Stencil (box, at);
108   m.translate (from);
109   return m;
110 }
111
112 Stencil
113 Line_interface::make_line (Real th, Offset from, Offset to)
114 {
115   SCM at = scm_list_n (ly_symbol2scm ("draw-line"),
116                        scm_from_double (th),
117                        scm_from_double (from[X_AXIS]),
118                        scm_from_double (from[Y_AXIS]),
119                        scm_from_double (to[X_AXIS]),
120                        scm_from_double (to[Y_AXIS]),
121                        SCM_UNDEFINED);
122
123   Box box;
124   box.add_point (from);
125   box.add_point (to);
126
127   box[X_AXIS].widen (th / 2);
128   box[Y_AXIS].widen (th / 2);
129
130   return Stencil (box, at);
131 }
132
133 Stencil
134 Line_interface::arrows (Grob *me, Offset from, Offset to,
135                         bool from_arrow,
136                         bool to_arrow)
137 {
138   Stencil a;
139   if (from_arrow || to_arrow)
140     {
141       Real thick = Staff_symbol_referencer::line_thickness (me)
142         * robust_scm2double (me->get_property ("thickness"), 1);
143       Real ss = Staff_symbol_referencer::staff_space (me);
144
145       Real len = robust_scm2double (me->get_property ("arrow-length"), 1.3 * ss);
146       Real wid = robust_scm2double (me->get_property ("arrow-width"), 0.5 * ss);
147
148       if (to_arrow)
149         a.add_stencil (make_arrow (from, to, thick, len, wid));
150
151       if (from_arrow)
152         a.add_stencil (make_arrow (to, from, thick, len, wid));
153     }
154
155   return a;
156 }
157
158 Stencil
159 Line_interface::line (Grob *me, Offset from, Offset to)
160 {
161   Real thick = Staff_symbol_referencer::line_thickness (me)
162     * robust_scm2double (me->get_property ("thickness"), 1);
163
164   SCM type = me->get_property ("style");
165   if (type == ly_symbol2scm ("zigzag"))
166     {
167       return zigzag_stencil (me, from, to);
168     }
169   Stencil stil;
170
171   SCM dash_fraction = me->get_property ("dash-fraction");
172   if (scm_is_number (dash_fraction) || type == ly_symbol2scm ("dotted-line"))
173     {
174
175       Real fraction
176         = type == ly_symbol2scm ("dotted-line")
177         ? 0.0
178         : robust_scm2double (dash_fraction, 0.4);
179
180       fraction = min (max (fraction, 0.0), 1.0);
181       Real period = Staff_symbol_referencer::staff_space (me)
182         * robust_scm2double (me->get_property ("dash-period"), 1.0);
183
184       if (period < 0)
185         return Stencil ();
186
187       stil = make_dashed_line (thick, from, to, period, fraction);
188     }
189   else
190     stil = make_line (thick, from, to);
191
192   return stil;
193 }
194
195 ADD_INTERFACE (Line_interface,
196                "Generic line objects. Any object using lines supports this.  Normally, "
197                "you get a straight line. If @code{dash-period} is defined, a dashed line is "
198                "produced; the length of the dashes is tuned with "
199                "@code{dash-fraction}. If the latter is set to 0, a dotted line is "
200                "produced. If @code{dash-fraction} is negative, the line is made "
201                "transparent.",
202
203                /* properties */
204                "dash-period "
205                "dash-fraction "
206                "thickness "
207                "style "
208                "zigzag-length "
209                "zigzag-width "
210                "arrow-length "
211                "arrow-width ")
212