]> git.donarmstrong.com Git - lilypond.git/blob - lily/tie-column.cc
* lily/tie-column.cc (werner_directions): new function
[lilypond.git] / lily / tie-column.cc
1 /*   
2   tie-column.cc --  implement Tie_column
3   
4   source file of the GNU LilyPond music typesetter
5   
6   (c) 2000--2003 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7   
8  */
9
10 #include "spanner.hh"
11 #include "tie-column.hh"
12 #include "group-interface.hh"
13 #include "tie.hh"
14 #include "directional-element-interface.hh"
15 #include "rhythmic-head.hh"
16
17
18
19
20
21
22 /*
23   tie dir depends on what Tie_column does.
24 */
25
26 void
27 Tie_column::add_tie (Grob*me,Grob *s)
28 {
29   if (s->get_parent (Y_AXIS)
30       && Tie_column::has_interface (s->get_parent (Y_AXIS)))
31     return ;
32   
33   if (!  Pointer_group_interface::count (me, "ties"))
34     {
35       dynamic_cast<Spanner*> (me)->set_bound (LEFT, Tie::head (s,LEFT));
36       dynamic_cast<Spanner*> (me)->set_bound (RIGHT, Tie::head (s,RIGHT));
37     }
38   s->set_parent (me, Y_AXIS);
39   Pointer_group_interface::add_grob (me, ly_symbol2scm ("ties"), s);
40   s->add_dependency (me);
41 }
42
43
44 void
45 Tie_column::set_directions (Grob*me)
46 {
47   werner_directions (me);
48 }
49   
50
51
52 int
53 tie_compare (Grob* const & s1,
54              Grob* const & s2)
55 {
56   return sign (Tie::get_position (s1) - Tie::get_position (s2));
57 }
58
59 /*
60   See [Ross p. 138].
61
62
63   In normal chord cases, the outer ties point outwards, and the
64   direction of the rest is determined by their staff position.
65
66   Ross forgets about the tie that is *on* the middle staff line. We
67   assume it goes UP. (TODO: make me settable) */
68 void
69 Tie_column::old_directions (Grob*me)
70 {
71   Link_array<Grob> ties =
72     Pointer_group_interface__extract_grobs (me, (Grob*)0, "ties");
73
74   for (int i = ties.size (); i--;)
75     if (get_grob_direction (ties[i]))
76       ties.del (i);
77   
78
79   if (!ties.size ())
80     return ;
81   
82
83   Direction d = get_grob_direction (me);
84   if (d)
85     {
86       for (int i = ties.size (); i--;)
87         {
88           Grob *  t = ties[i];
89           set_grob_direction (t, d);
90         }
91       return;
92     }
93   
94   if (ties.size () == 1)
95     {
96       Grob *  t = ties[0];      
97       set_grob_direction (t,Tie::get_default_dir (t));
98       return;
99     }
100   
101   ties.sort (tie_compare);
102   set_grob_direction (ties[0], DOWN);
103   ties.del (0);
104   
105   set_grob_direction (ties.pop (), UP);
106   for (int i=ties.size (); i--;)
107     {
108       Grob *  t = ties[i];
109       Real p = Tie::get_position (t);
110       Direction d = (Direction) sign (p);
111       if (!d)
112         d = UP;
113       set_grob_direction (t, d);
114     }
115   
116 }
117
118 /*
119   
120 % . The algorithm to choose the direction of the ties doesn't work
121 %   properly.  I suggest the following for applying ties sequentially
122 %   from top to bottom:
123 %
124 %     + The topmost tie is always `up'.
125 %
126 %     + If there is a vertical gap to the last note above larger than
127 %       or equal to a fifth (or sixth?), the tie is `up', otherwise it
128 %       is `down'.
129 %
130 %     + The bottommost tie is always `down'.
131
132  */
133 void
134 Tie_column::werner_directions (Grob *me)
135 {
136   Link_array<Grob> ties =
137     Pointer_group_interface__extract_grobs (me, (Grob*)0, "ties");
138
139   if (!ties.size ())
140     return ;
141   
142   ties.sort (tie_compare);
143
144   Direction d = get_grob_direction (me);
145   if (d)
146     {
147       for (int i = ties.size (); i--;)
148         {
149           Grob *  t = ties[i];
150           if (!get_grob_direction (t))
151             set_grob_direction (t, d);
152         }
153       return ;
154     }
155   
156   if (ties.size () == 1)
157     {
158       Grob *  t = ties[0];      
159       set_grob_direction (t,Tie::get_default_dir (t));
160       return ;
161     }
162
163   Real last_down_pos = 10000;
164   if (!get_grob_direction (ties[0]))
165     set_grob_direction (ties[0], DOWN);
166   
167   for (int i = ties.size (); i--;)
168     {
169       Grob *t = ties[i];
170       
171       Direction d = get_grob_direction (t);
172       Real p  = Tie::get_position (t);
173       if (!d)
174         {
175           if (last_down_pos - p  > 5)
176             {
177               d = UP;
178             }
179           else
180             {
181               d = DOWN;
182             }
183
184           set_grob_direction (t, d);
185         }
186
187       if (d == DOWN)
188         last_down_pos = p;
189     }
190
191   return ;
192 }
193
194
195 MAKE_SCHEME_CALLBACK (Tie_column,after_line_breaking,1);
196 SCM
197 Tie_column::after_line_breaking (SCM smob)
198 {
199   werner_directions (unsmob_grob (smob));
200   return SCM_UNSPECIFIED;
201 }
202
203
204
205 ADD_INTERFACE (Tie_column,"tie-column-interface",
206   "that sets tie directions in a tied chord",
207   "direction");
208