]> git.donarmstrong.com Git - lilypond.git/blob - lily/arpeggio.cc
ADD_INTERFACE: Formatting and fixing typos.
[lilypond.git] / lily / arpeggio.cc
1 /*
2   arpeggio.cc -- implement Arpeggio
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 2000--2007 Jan Nieuwenhuizen <janneke@gnu.org>
7 */
8
9 #include "arpeggio.hh"
10
11 #include "grob.hh"
12 #include "output-def.hh"
13 #include "stem.hh"
14 #include "staff-symbol-referencer.hh"
15 #include "staff-symbol.hh"
16 #include "warn.hh"
17 #include "font-interface.hh"
18 #include "lookup.hh"
19 #include "pointer-group-interface.hh"
20
21 Grob *
22 Arpeggio::get_common_y (Grob *me)
23 {
24   Grob *common = me;
25
26   extract_grob_set (me, "stems", stems);
27   for (vsize i = 0; i < stems.size (); i++)
28     {
29       Grob *stem = stems[i];
30       common = common->common_refpoint (Staff_symbol_referencer::get_staff_symbol (stem),
31                                         Y_AXIS);
32     }
33
34   return common;
35 }
36
37 MAKE_SCHEME_CALLBACK(Arpeggio, calc_positions, 1);
38 SCM
39 Arpeggio::calc_positions (SCM grob)
40 {
41   Grob *me = unsmob_grob (grob);
42   Grob *common = get_common_y (me);
43   
44   /*
45     TODO:
46
47     Using stems here is not very convenient; should store noteheads
48     instead, and also put them into the support. Now we will mess up
49     in vicinity of a collision.
50   */
51   Interval heads;
52   Real my_y = me->relative_coordinate (common, Y_AXIS);
53
54   extract_grob_set (me, "stems", stems);
55   for (vsize i = 0; i < stems.size (); i++)
56     {
57       Grob *stem = stems[i];
58       Grob *ss = Staff_symbol_referencer::get_staff_symbol (stem);
59       Interval iv = Stem::head_positions (stem);
60       iv *= Staff_symbol::staff_space (ss) / 2.0;
61
62       heads.unite (iv + ss->relative_coordinate (common, Y_AXIS)
63                    - my_y);
64     }
65
66   heads *= 1/Staff_symbol_referencer::staff_space(me);
67
68   return ly_interval2scm (heads);
69 }
70
71 MAKE_SCHEME_CALLBACK (Arpeggio, print, 1);
72 SCM
73 Arpeggio::print (SCM smob)
74 {
75   Grob *me = unsmob_grob (smob);
76   Interval heads = robust_scm2interval (me->get_property ("positions"),
77                                         Interval())
78     * Staff_symbol_referencer::staff_space (me);
79   
80   if (heads.is_empty () || heads.length () < 0.5)
81     {
82       if (!to_boolean (me->get_property ("transparent")))
83         {
84           me->warning ("no heads for arpeggio found?");
85           me->suicide ();
86         }
87       return SCM_EOL;
88     }
89
90   SCM ad = me->get_property ("arpeggio-direction");
91   Direction dir = CENTER;
92   if (is_direction (ad))
93     dir = to_dir (ad);
94
95   Stencil mol;
96   Font_metric *fm = Font_interface::get_default_font (me);
97   Stencil squiggle = fm->find_by_name ("scripts.arpeggio");
98
99   Stencil arrow;
100   if (dir)
101     {
102       arrow = fm->find_by_name ("scripts.arpeggio.arrow." + to_string (dir));
103       heads[dir] -= dir * arrow.extent (Y_AXIS).length ();
104     }
105
106   for (Real y = heads[LEFT]; y < heads[RIGHT];
107        y += squiggle.extent (Y_AXIS).length ())
108     mol.add_at_edge (Y_AXIS, UP, squiggle, 0.0);
109
110   mol.translate_axis (heads[LEFT], Y_AXIS);
111   if (dir)
112     mol.add_at_edge (Y_AXIS, dir, arrow, 0);
113
114   return mol.smobbed_copy ();
115 }
116
117 /* Draws a vertical bracket to the left of a chord
118    Chris Jackson <chris@fluffhouse.org.uk> */
119
120 MAKE_SCHEME_CALLBACK (Arpeggio, brew_chord_bracket, 1);
121 SCM
122 Arpeggio::brew_chord_bracket (SCM smob)
123 {
124   Grob *me = unsmob_grob (smob);
125   Interval heads = robust_scm2interval (me->get_property ("positions"),
126                                         Interval())
127     * Staff_symbol_referencer::staff_space (me);
128
129   Real lt = me->layout ()->get_dimension (ly_symbol2scm ("line-thickness"));
130   Real sp = 1.5 * Staff_symbol_referencer::staff_space (me);
131   Real dy = heads.length () + sp;
132   Real x = 0.7;
133
134   Stencil mol (Lookup::bracket (Y_AXIS, Interval (0, dy), lt, x, lt));
135   mol.translate_axis (heads[LEFT] - sp / 2.0, Y_AXIS);
136   return mol.smobbed_copy ();
137 }
138
139 /*
140   We have to do a callback, because print () triggers a
141   vertical alignment if it is cross-staff.
142 */
143 MAKE_SCHEME_CALLBACK (Arpeggio, width, 1);
144 SCM
145 Arpeggio::width (SCM smob)
146 {
147   Grob *me = unsmob_grob (smob);
148   Stencil arpeggio = Font_interface::get_default_font (me)->find_by_name ("scripts.arpeggio");
149
150   return ly_interval2scm (arpeggio.extent (X_AXIS));
151 }
152
153 MAKE_SCHEME_CALLBACK (Arpeggio, height, 1);
154 SCM
155 Arpeggio::height (SCM smob)
156 {
157   return Grob::stencil_height (smob);
158 }
159
160 MAKE_SCHEME_CALLBACK (Arpeggio, pure_height, 3);
161 SCM
162 Arpeggio::pure_height (SCM smob, SCM, SCM)
163 {
164   Grob *me = unsmob_grob (smob);
165   if (to_boolean (me->get_property ("cross-staff")))
166     return ly_interval2scm (Interval ());
167
168   return height (smob);
169 }
170
171 ADD_INTERFACE (Arpeggio,
172                "Functions and settings for drawing an arpeggio symbol (a "
173                "wavy line left to noteheads.",
174
175                /* properties */
176                "arpeggio-direction "
177                "positions "
178                "script-priority " // TODO: make around-note-interface
179                "stems "
180                );
181