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