]> git.donarmstrong.com Git - lilypond.git/blob - lily/tie-formatting-problem.cc
oops. Include $CONFIGFILE.make, not
[lilypond.git] / lily / tie-formatting-problem.cc
1 /*
2   tie-formatting-problem.cc -- implement Tie_formatting_problem6
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 2005 Han-Wen Nienhuys <hanwen@xs4all.nl>
7
8 */
9
10 #include "tie-formatting-problem.hh"
11
12 #include "directional-element-interface.hh"
13 #include "staff-symbol-referencer.hh"
14 #include "tie.hh"
15
16 #include "item.hh"
17 #include "spanner.hh" 
18
19 #include "stem.hh"
20 #include "note-head.hh"
21 #include "rhythmic-head.hh"
22
23 Interval
24 Tie_formatting_problem::get_attachment (Real y) const
25 {
26   Interval attachments;
27   Direction d = LEFT;
28   do
29     {
30       attachments[d] = skyline_height (chord_outlines_[d], y, -d);
31     }
32   while (flip (&d) != LEFT);
33   
34   return attachments;
35 }
36
37
38
39
40 Tie_formatting_problem::Tie_formatting_problem()
41 {
42   x_refpoint_ = 0;
43   
44 }
45
46 void
47 Tie_formatting_problem::set_chord_outline (Link_array<Item> bounds,
48                                            Direction d)
49 {
50   Real staff_space = Staff_symbol_referencer::staff_space (bounds[0]);
51
52   Array<Box> boxes;
53
54   Grob *stem = 0;
55   for (int i = 0; i < bounds.size (); i++)
56     {
57       Grob *head = bounds[i];
58       if (!Note_head::has_interface (head))
59         continue;
60       
61       if (!stem)
62         stem = unsmob_grob (head->get_object ("stem"));
63           
64       Real p = Staff_symbol_referencer::get_position (head);
65       Interval y ((p-1) * 0.5 * staff_space,
66                   (p+1) * 0.5 * staff_space);
67
68       Interval x = head->extent (x_refpoint_, X_AXIS);
69       boxes.push (Box (x, y));
70
71       Grob *dots = Rhythmic_head::get_dots (head);
72       if (d == LEFT && dots)
73         {
74           Interval x = dots->extent (x_refpoint_, X_AXIS);
75           Interval y (-0.5, 0.5);
76           y.translate (Staff_symbol_referencer::get_position (dots));
77           y *= staff_space * 0.5;
78           
79           boxes.push (Box (x, y));
80         }
81     }
82
83   chord_outlines_[d] = empty_skyline (-d);
84
85   if (bounds[0]->break_status_dir ())
86     {
87       Real x = robust_relative_extent (bounds[0],  x_refpoint_, X_AXIS)[-d];
88       chord_outlines_[d].elem_ref (0).height_ = x; 
89     }
90           
91   for (int i = 0; i < boxes.size (); i++)
92     insert_extent_into_skyline (&chord_outlines_[d]  ,
93                                 boxes[i], Y_AXIS, -d);
94
95   if (stem
96       && !Stem::is_invisible (stem))
97     {
98       Interval x;
99       x.add_point (stem->relative_coordinate (x_refpoint_, X_AXIS));
100       x.widen (staff_space / 20); // ugh.
101       Interval y;
102       y.add_point (Stem::stem_end_position (stem) * staff_space * .5);
103
104       Direction stemdir = get_grob_direction (stem);
105       y.add_point (Stem::head_positions (stem)[-stemdir]
106                    * staff_space * .5);
107           
108       insert_extent_into_skyline (&chord_outlines_[d], Box (x,y), Y_AXIS, -d);
109
110
111
112       if (d == LEFT)
113         {
114           Box flag_box = Stem::get_translated_flag (stem).extent_box ();
115           flag_box.translate( Offset (x[RIGHT], X_AXIS));
116           insert_extent_into_skyline (&chord_outlines_[d], flag_box,
117                                       Y_AXIS, -d);
118         }
119     }
120   
121   Direction updowndir = DOWN;
122   do
123     {
124       Interval x ;
125       Interval y;
126       if (boxes.size())
127         {
128           Box b = boxes.boundary (updowndir, 0);
129           x = b[X_AXIS];
130           x[-d] =  b[X_AXIS].linear_combination (-d / 2);
131           y[-updowndir] = b[Y_AXIS][updowndir];
132           y[updowndir] = updowndir * infinity_f;
133         }
134
135       if (!x.is_empty ())
136         insert_extent_into_skyline (&chord_outlines_[d],
137                                     Box (x,y),
138                                     Y_AXIS, -d);
139     }
140   while (flip (&updowndir) != DOWN);
141
142   for (int i = 0; i < bounds.size (); i++)
143     {
144       if (!Note_head::has_interface (bounds[i]))
145         continue;
146
147       
148       Grob *dots = unsmob_grob (bounds[i]->get_object ("dot"));
149       if (dots && d == LEFT)
150         {
151           Interval x = dots->extent (x_refpoint_, X_AXIS);
152           Real p = Staff_symbol_referencer::get_position (dots);
153               
154           Interval y (-1,1);
155           y *= (staff_space /4);
156           y.translate (p * staff_space * .5);
157
158           insert_extent_into_skyline (&chord_outlines_[d],
159                                       Box (x,y), Y_AXIS, -d);
160         }
161     }
162 }
163
164
165 void
166 Tie_formatting_problem::from_tie (Grob *tie)
167 {
168   Link_array<Grob> ties;
169   ties.push (tie);
170
171   from_ties (ties);
172
173   details_.from_grob (tie);
174 }
175
176 Grob *
177 Tie_formatting_problem::common_x_refpoint () const
178 {
179   return x_refpoint_;
180 }
181
182 void
183 Tie_formatting_problem::from_ties (Link_array<Grob> const &ties)
184 {
185   if (ties.is_empty ())
186     return;
187   
188   x_refpoint_ = ties[0];
189   details_.from_grob (ties[0]);
190   for (int i = 0; i < ties.size (); i++)
191     {
192       x_refpoint_ = dynamic_cast<Spanner*> (ties[i])->get_bound (LEFT)->common_refpoint (x_refpoint_, X_AXIS); 
193       x_refpoint_ = dynamic_cast<Spanner*> (ties[i])->get_bound (RIGHT)->common_refpoint (x_refpoint_, X_AXIS); 
194     }
195   
196   Direction d = LEFT;
197   do
198     {
199       Link_array<Item> bounds;
200       
201       for (int i = 0; i < ties.size (); i++)
202         {
203           Item *it = dynamic_cast<Spanner*> (ties[i])->get_bound (d);
204                                              
205           bounds.push (it);
206         }
207       
208       set_chord_outline (bounds, d);
209     }
210   while (flip (&d) != LEFT);
211 }
212
213 void
214 Tie_formatting_problem::from_lv_ties (Link_array<Grob> const &lv_ties)
215 {
216   if (lv_ties.is_empty ())
217     return ;
218   
219   details_.from_grob (lv_ties[0]);
220   Link_array<Item> heads;
221   for (int i = 0; i < lv_ties.size (); i++)
222     {
223       Item *head = unsmob_item (lv_ties[i]->get_object ("note-head"));
224       heads.push (head);
225     }
226
227   x_refpoint_ = lv_ties [0];
228   for (int i = 0; i < lv_ties.size (); i++)
229     {
230       x_refpoint_ = lv_ties[i]->common_refpoint (x_refpoint_, X_AXIS); 
231     }
232
233   set_chord_outline (heads, LEFT);
234
235   Real right_most = - infinity_f;   
236
237   for (int i = 0; i < chord_outlines_[LEFT].size (); i++)
238     {
239       right_most = max (right_most, chord_outlines_[LEFT][i].height_);
240     }
241
242   Skyline_entry right_entry;
243   right_entry.width_.set_full ();
244   right_entry.height_ = right_most + 1.5;
245   
246   chord_outlines_[RIGHT].push (right_entry);
247 }