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