]> git.donarmstrong.com Git - lilypond.git/blob - lily/line-interface.cc
* lily/paper-score.cc (process): run get_paper_systems() only once.
[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--2005 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
15 Stencil
16 Line_interface::make_arrow (Offset beg, Offset end,
17                             Real thick,
18                             Real length, Real width)
19 {
20   Real angle = (end - beg).arg();
21   Array<Offset> points;
22   
23   //construct the arrow
24   points.push (Offset (0, 0));
25   points.push (Offset (length, width));
26   points.push (Offset (length, -width));
27
28   // rotate and translate the arrow
29   for (int i = 0; i < points.size(); i++)
30     points[i] = points[i] * complex_exp (Offset (0, angle)) + beg;
31     
32   // we must shorten the line half of arrow length
33   // to prevent the line from sticking out
34   beg = beg + Offset (length/2,0) * complex_exp (Offset (0, angle));
35   
36   return (Lookup::round_filled_polygon (points, thick));
37 }
38
39 Stencil
40 Line_interface::make_dashed_line (Real thick, Offset from, Offset to,
41                                   Real dash_period, Real dash_fraction)
42 {
43   dash_fraction = (dash_fraction >? 0) <? 1.0;
44   Real on = dash_fraction * dash_period + thick;
45   Real off = dash_period - on;
46
47   SCM at = scm_list_n (ly_symbol2scm ("dashed-line"),
48                        scm_make_real (thick),
49                        scm_make_real (on),
50                        scm_make_real (off),
51                        scm_make_real (to[X_AXIS] - from[X_AXIS]),
52                        scm_make_real (to[Y_AXIS] - from[Y_AXIS]),
53                        SCM_UNDEFINED);
54
55   Box box;
56   box.add_point (Offset (0, 0));
57   box.add_point (to - from);
58
59   box[X_AXIS].widen (thick / 2);
60   box[Y_AXIS].widen (thick / 2);
61
62   Stencil m = Stencil (box, at);
63   m.translate (from);
64   return m;
65 }
66
67 Stencil
68 Line_interface::make_line (Real th, Offset from, Offset to)
69 {
70   SCM at = scm_list_n (ly_symbol2scm ("draw-line"),
71                        scm_make_real (th),
72                        scm_make_real (from[X_AXIS]),
73                        scm_make_real (from[Y_AXIS]),
74                        scm_make_real (to[X_AXIS]),
75                        scm_make_real (to[Y_AXIS]),
76                        SCM_UNDEFINED);
77
78   Box box;
79   box.add_point (from);
80   box.add_point (to);
81
82   box[X_AXIS].widen (th / 2);
83   box[Y_AXIS].widen (th / 2);
84
85   return Stencil (box, at);
86 }
87
88 Stencil
89 Line_interface::arrows (Grob *me, Offset from, Offset to,
90                         bool from_arrow,
91                         bool to_arrow)
92 {
93   Stencil a;
94   if (from_arrow || to_arrow)
95     {
96       Real thick = Staff_symbol_referencer::line_thickness (me)
97         * robust_scm2double (me->get_property ("thickness"), 1);
98       Real len = robust_scm2double (me->get_property ("arrow-length"), 1.3);
99       Real wid = robust_scm2double (me->get_property ("arrow-width"), 0.5);
100
101       if (to_arrow)
102         a.add_stencil (make_arrow (from, to, thick, len, wid));
103         
104       if (from_arrow)
105         a.add_stencil (make_arrow (to, from, thick, len, wid));
106     }
107
108   return a;
109 }
110                         
111
112 Stencil
113 Line_interface::line (Grob *me, Offset from, Offset to)
114 {
115   Real thick = Staff_symbol_referencer::line_thickness (me)
116     * robust_scm2double (me->get_property ("thickness"), 1);
117
118   SCM type = me->get_property ("style");
119
120   Stencil l;
121   
122   SCM dash_fraction = me->get_property ("dash-fraction");
123   if (scm_is_number (dash_fraction) || type == ly_symbol2scm ("dotted-line"))
124     {
125
126       Real fraction
127         = type == ly_symbol2scm ("dotted-line")
128         ? 0.0
129         : robust_scm2double (dash_fraction, 0.4);
130
131       fraction = (fraction >? 0) <? 1.0;
132       Real period = Staff_symbol_referencer::staff_space (me)
133         * robust_scm2double (me->get_property ("dash-period"), 1.0);
134
135       if (period < 0)
136         return Stencil ();
137
138       l =  make_dashed_line (thick, from, to, period, fraction);
139     }
140   else
141     {
142       l =  make_line (thick, from, to);
143     }
144
145   return l;
146 }
147
148 ADD_INTERFACE (Line_interface, "line-interface",
149                "Generic line objects. Any object using lines supports this.  Normally, "
150                "you get a straight line. If @code{dash-period} is defined, a dashed line is "
151                "produced; the length of the dashes is tuned with "
152                "@code{dash-fraction}. If the latter is set to 0, a dotted line is "
153                "produced. If @code{dash-fraction} is negative, the line is made "
154                "transparent.",
155
156                "dash-period dash-fraction thickness style arrow-length arrow-width")