2 slur.cc -- implement Slur
4 source file of the GNU LilyPond music typesetter
6 (c) 1996, 1997--1998, 1998 Han-Wen Nienhuys <hanwen@stack.nl>
7 Jan Nieuwenhuizen <jan@digicash.com>
12 * begin and end should be treated as a Script.
14 * slur from notehead to stemend: c''()b''
20 #include "paper-def.hh"
21 #include "note-column.hh"
24 #include "molecule.hh"
28 #include "encompass-info.hh"
31 IMPLEMENT_IS_TYPE_B1(Slur,Bow);
38 Slur::add (Note_column*n)
40 encompass_arr_.push (n);
45 Slur::set_default_dir ()
48 for (int i=0; i < encompass_arr_.size (); i ++)
50 if (encompass_arr_[i]->dir_ < 0)
59 Slur::do_add_processing ()
61 set_bounds (LEFT, encompass_arr_[0]);
62 if (encompass_arr_.size () > 1)
63 set_bounds (RIGHT, encompass_arr_.top ());
67 Slur::do_pre_processing ()
69 // don't set directions
73 Slur::do_substitute_dependency (Score_elem*o, Score_elem*n)
76 while ((i = encompass_arr_.find_i ((Note_column*)o->item ())) >=0)
79 encompass_arr_[i] = (Note_column*)n->item ();
81 encompass_arr_.del (i);
86 Note_column_compare (Note_column *const&n1 , Note_column* const&n2)
88 return Item::left_right_compare (n1, n2);
92 Slur::do_post_processing ()
94 encompass_arr_.sort (Note_column_compare);
98 Real interline = paper ()->interline_f ();
99 Real internote = interline / 2;
100 Real notewidth = paper ()->note_width ();
101 Real const SLUR_MIN = 2.0 * interline;
104 [OSU]: slur and tie placement
107 * x = centre of head (upside-down: inner raakpunt stem) - d * gap
109 * y = length < 5ss : horizontal raakpunt + d * 0.25 ss
110 y = length >= 5ss : y next interline - d * 0.25 ss
111 --> height <= 5 length ?? we use <= 3 length, now...
113 * suggested gap = ss / 5;
115 // jcn: 1/5 seems so small?
116 Real gap_f = interline / 2; // 5;
118 Drul_array<Note_column*> extrema;
119 extrema[LEFT] = encompass_arr_[0];
120 extrema[RIGHT] = encompass_arr_.top ();
129 if (extrema[d] != spanned_drul_[d])
132 *(spanned_drul_[d]->width ().length () -0.5*notewidth);
135 if ((extrema[u] == spanned_drul_[u]) && extrema[u]->stem_l_)
137 dy_f_drul_[d] = extrema[u]->stem_l_->height ()[dir_];
138 dy_f_drul_[u] = extrema[u]->stem_l_->height ()[dir_];
144 dx_f_drul_[LEFT] = spanned_drul_[LEFT]->width ().length ();
145 // dx_f_drul_[LEFT] -= 2 * notewidth;
148 if (encompass_arr_.size () > 1)
149 dx_f_drul_[RIGHT] += notewidth;
154 dy_f_drul_[d] += 2.0 * dir_ * internote;
159 else if (extrema[d]->stem_l_ && !extrema[d]->stem_l_->transparent_b_)
161 dy_f_drul_[d] = (int)rint (extrema[d]->stem_l_->height ()[dir_]);
162 dx_f_drul_[d] += 0.5 * notewidth - d * gap_f;
163 if (dir_ == extrema[d]->stem_l_->dir_)
166 dx_f_drul_[d] += 0.5 * (dir_ * d) * d * notewidth;
168 dx_f_drul_[d] += 0.25 * (dir_ * d) * d * notewidth;
173 dy_f_drul_[d] = (int)rint (extrema[d]->head_positions_interval ()
176 dy_f_drul_[d] += dir_ * interline;
178 while (flip(&d) != LEFT);
180 // now that both are set, do dependent
186 if (extrema[d] != spanned_drul_[d])
189 if (dx_f_drul_[RIGHT] - dx_f_drul_[LEFT] < SLUR_MIN)
191 dx_f_drul_[d] -= d * SLUR_MIN
192 - (dx_f_drul_[RIGHT] - dx_f_drul_[LEFT]);
193 dx_f_drul_[d] = dx_f_drul_[(Direction)-d] + d * SLUR_MIN;
195 dy_f_drul_[d] = dy_f_drul_[(Direction)-d];
198 while (flip(&d) != LEFT);
202 Slur::get_encompass_offset_arr () const
204 Offset left = Offset (dx_f_drul_[LEFT], dy_f_drul_[LEFT]);
205 left.x () += encompass_arr_[0]->stem_l_->hpos_f ();
207 Offset d = Offset (dx_f_drul_[RIGHT] - dx_f_drul_[LEFT],
208 dy_f_drul_[RIGHT] - dy_f_drul_[LEFT]);
209 d.x () += width ().length ();
212 int last = encompass_arr_.size () - 1;
215 if (encompass_arr_[0] != spanned_drul_[LEFT])
219 if (encompass_arr_.top () != spanned_drul_[RIGHT])
226 notes.push (Offset (0,0));
228 for (int i = first; i < last; i++)
230 Encompass_info info (encompass_arr_[i], dir_);
231 notes.push (info.o_ - left);
237 int n = last - first + 2;
238 Array<Offset> notes (n);
239 notes[0] = Offset (0,0);
241 for (int i = first; i < last; i++)
243 Encompass_info info (encompass_arr_[i], dir_);
244 notes[i - first + 1] = info.o_ - left;
246 notes[n - 1] = Offset (d);