]> git.donarmstrong.com Git - lilypond.git/blob - lily/tie-column.cc
* lily/include/music-iterator.hh (class Music_iterator): add
[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   TODO: this doesn't follow standard pattern. Regularize.
27  */
28 void
29 Tie_column::add_tie (Grob*me,Grob *s)
30 {
31   if (s->get_parent (Y_AXIS)
32       && Tie_column::has_interface (s->get_parent (Y_AXIS)))
33     return ;
34   
35   if (!  Pointer_group_interface::count (me, "ties"))
36     {
37       dynamic_cast<Spanner*> (me)->set_bound (LEFT, Tie::head (s,LEFT));
38       dynamic_cast<Spanner*> (me)->set_bound (RIGHT, Tie::head (s,RIGHT));
39     }
40   s->set_parent (me, Y_AXIS);
41   Pointer_group_interface::add_grob (me, ly_symbol2scm ("ties"), s);
42   s->add_dependency (me);
43 }
44
45
46 void
47 Tie_column::set_directions (Grob*me)
48 {
49   werner_directions (me);
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   if (!ties.size ())
79     return ;
80
81   Direction d = get_grob_direction (me);
82   if (d)
83     {
84       for (int i = ties.size (); i--;)
85         {
86           Grob *  t = ties[i];
87           set_grob_direction (t, d);
88         }
89       return;
90     }
91   
92   if (ties.size () == 1)
93     {
94       Grob *  t = ties[0];      
95       set_grob_direction (t,Tie::get_default_dir (t));
96       return;
97     }
98   
99   ties.sort (tie_compare);
100   set_grob_direction (ties[0], DOWN);
101   ties.del (0);
102   
103   set_grob_direction (ties.pop (), UP);
104   for (int i=ties.size (); i--;)
105     {
106       Grob *  t = ties[i];
107       Real p = Tie::get_position (t);
108       Direction d = (Direction) sign (p);
109       if (!d)
110         d = UP;
111       set_grob_direction (t, d);
112     }
113   
114 }
115
116 /*
117   
118 % . The algorithm to choose the direction of the ties doesn't work
119 %   properly.  I suggest the following for applying ties sequentially
120 %   from top to bottom:
121 %
122 %     + The topmost tie is always `up'.
123 %
124 %     + If there is a vertical gap to the last note above larger than
125 %       or equal to a fifth (or sixth?), the tie is `up', otherwise it
126 %       is `down'.
127 %
128 %     + The bottommost tie is always `down'.
129
130  */
131 void
132 Tie_column::werner_directions (Grob *me)
133 {
134   Link_array<Grob> ties =
135     Pointer_group_interface__extract_grobs (me, (Grob*)0, "ties");
136
137   if (!ties.size ())
138     return ;
139   
140   ties.sort (tie_compare);
141
142   Direction d = get_grob_direction (me);
143   if (d)
144     {
145       for (int i = ties.size (); i--;)
146         {
147           Grob *  t = ties[i];
148           if (!get_grob_direction (t))
149             set_grob_direction (t, d);
150         }
151       return ;
152     }
153   
154   if (ties.size () == 1)
155     {
156       Grob *  t = ties[0];      
157       set_grob_direction (t,Tie::get_default_dir (t));
158       return ;
159     }
160
161   Real last_down_pos = 10000;
162   if (!get_grob_direction (ties[0]))
163     set_grob_direction (ties[0], DOWN);
164   
165   for (int i = ties.size (); i--;)
166     {
167       Grob *t = ties[i];
168       
169       Direction d = get_grob_direction (t);
170       Real p  = Tie::get_position (t);
171       if (!d)
172         {
173           if (last_down_pos - p  > 5)
174             {
175               d = UP;
176             }
177           else
178             {
179               d = DOWN;
180             }
181
182           set_grob_direction (t, d);
183         }
184
185       if (d == DOWN)
186         last_down_pos = p;
187     }
188
189   return ;
190 }
191
192
193 MAKE_SCHEME_CALLBACK (Tie_column,after_line_breaking,1);
194 SCM
195 Tie_column::after_line_breaking (SCM smob)
196 {
197   werner_directions (unsmob_grob (smob));
198   return SCM_UNSPECIFIED;
199 }
200
201
202
203 ADD_INTERFACE (Tie_column,"tie-column-interface",
204   "that sets tie directions in a tied chord",
205   "direction");
206