]> git.donarmstrong.com Git - lilypond.git/blob - lily/arpeggio.cc
*** empty log message ***
[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--2004 Jan Nieuwenhuizen <janneke@gnu.org>
7  */
8
9 #include "arpeggio.hh"
10
11 #include "output-def.hh"
12 #include "stem.hh"
13 #include "staff-symbol-referencer.hh"
14 #include "staff-symbol.hh"
15 #include "warn.hh"
16 #include "font-interface.hh"
17 #include "lookup.hh"
18
19
20 MAKE_SCHEME_CALLBACK (Arpeggio, print, 1);
21 SCM 
22 Arpeggio::print (SCM smob) 
23 {
24   Grob *me = unsmob_grob (smob);
25   
26   Grob * common = me;
27   for (SCM s = me->get_property ("stems"); scm_is_pair (s); s = scm_cdr (s))
28     {
29       Grob * stem =  unsmob_grob (scm_car (s));
30       common =  common->common_refpoint (Staff_symbol_referencer::get_staff_symbol (stem),
31                                  Y_AXIS);
32     }
33
34   /*
35     TODO:
36     
37     Using stems here is not very convenient; should store noteheads
38     instead, and also put them into the support. Now we will mess up
39     in vicinity of a collision.
40
41   */
42   Interval heads;
43   Real my_y = me->relative_coordinate (common, Y_AXIS);
44       
45   for (SCM s = me->get_property ("stems"); scm_is_pair (s); s = scm_cdr (s))
46     {
47       Grob * stem = unsmob_grob (scm_car (s));
48       Grob * ss = Staff_symbol_referencer::get_staff_symbol (stem);
49       Interval iv = Stem::head_positions (stem);
50       iv *= Staff_symbol::staff_space (ss)/2.0;
51       
52       heads.unite (iv + ss->relative_coordinate (common, Y_AXIS)
53                    - my_y);
54     }
55
56   if (heads.is_empty ())
57     {
58       /*
59         Dumb blonde error
60
61         :-)
62        */
63       programming_error ("Huh, no heads for arpeggio found.");
64       return SCM_EOL;
65     }
66
67   SCM ad = me->get_property ("arpeggio-direction");
68   Direction dir = CENTER;
69   if (is_direction (ad))
70     {
71       dir = to_dir (ad);
72     }
73   
74   Stencil mol;
75   Font_metric *fm = Font_interface::get_default_font (me);
76   Stencil squiggle = fm->find_by_name ("scripts-arpeggio");
77
78   Stencil arrow ;  
79   if (dir)
80     {
81       arrow = fm->find_by_name ("scripts-arpeggio-arrow-" + to_string (dir));
82       heads[dir] -= dir * arrow.extent (Y_AXIS).length ();
83     }
84   
85   for (Real  y = heads[LEFT] ; y < heads[RIGHT];
86        y+= squiggle. extent (Y_AXIS).length ())
87       mol.add_at_edge (Y_AXIS, UP,squiggle, 0.0, 0);
88
89   mol.translate_axis (heads[LEFT], Y_AXIS);
90   if (dir)
91     mol.add_at_edge (Y_AXIS, dir,arrow, 0,0);
92   
93   return mol.smobbed_copy () ;
94 }
95
96 /* Draws a vertical bracket to the left of a chord 
97    Chris Jackson <chris@fluffhouse.org.uk> */
98
99 MAKE_SCHEME_CALLBACK (Arpeggio, brew_chord_bracket, 1);
100 SCM 
101 Arpeggio::brew_chord_bracket (SCM smob) 
102 {
103   Grob *me = unsmob_grob (smob);
104   
105   Grob * common = me;
106   for (SCM s = me->get_property ("stems"); scm_is_pair (s); s = scm_cdr (s))
107     {
108       Grob * stem =  unsmob_grob (scm_car (s));
109       common =  common->common_refpoint (Staff_symbol_referencer::get_staff_symbol (stem),
110                                  Y_AXIS);
111     }
112
113   Interval heads;
114   Real my_y = me->relative_coordinate (common, Y_AXIS);
115       
116   for (SCM s = me->get_property ("stems"); scm_is_pair (s); s = scm_cdr (s))
117     {
118       Grob * stem = unsmob_grob (scm_car (s));
119       Grob * ss = Staff_symbol_referencer::get_staff_symbol (stem);
120       Interval iv = Stem::head_positions (stem);
121       iv *= Staff_symbol::staff_space (ss)/2.0;      
122       heads.unite (iv  +  ss->relative_coordinate (common, Y_AXIS)  -  my_y);
123     }
124
125   Real lt =  me->get_layout ()->get_dimension (ly_symbol2scm ("linethickness"));
126   Real sp = 1.5 * Staff_symbol_referencer::staff_space (me);
127   Real dy = heads.length () + sp;
128   Real x = 0.7;
129
130   Stencil mol (Lookup::bracket (Y_AXIS, Interval (0, dy), lt, x, lt));
131   mol.translate_axis (heads[LEFT] - sp/2.0, Y_AXIS);
132   return mol.smobbed_copy ();
133 }
134
135
136 /*
137   We have to do a callback, because print () triggers a
138   vertical alignment if it is cross-staff.
139 */
140 MAKE_SCHEME_CALLBACK (Arpeggio, width_callback,2);
141 SCM
142 Arpeggio::width_callback (SCM smob, SCM axis)
143 {
144   Grob * me = unsmob_grob (smob);
145   Axis a = (Axis)scm_to_int (axis);
146   assert (a == X_AXIS);
147   Stencil arpeggio = Font_interface::get_default_font (me)->find_by_name ("scripts-arpeggio");
148
149   return ly_interval2scm (arpeggio.extent (X_AXIS));
150 }
151
152
153 ADD_INTERFACE (Arpeggio, "arpeggio-interface",
154   "Functions and settings for drawing an arpeggio symbol (a wavy line left to noteheads.",
155   "stems arpeggio-direction");
156