]> git.donarmstrong.com Git - lilypond.git/blob - lily/tie-column.cc
Configure only pristine build tree or on user
[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--2004 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       if (t->is_live ()
158           && !get_grob_direction (t))
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   "Object that sets directions of multiple ties in a tied chord",
207   "direction");
208