2 slur.cc -- implement Slur
4 source file of the GNU LilyPond music typesetter
6 (c) 1996, 1997 Han-Wen Nienhuys <hanwen@stack.nl>
12 think about crossing stems.
13 Begin and end should be treated as a Script.
18 #include "paper-def.hh"
19 #include "note-column.hh"
22 #include "molecule.hh"
28 Slur::add (Note_column*n)
30 encompass_arr_.push (n);
35 Slur::set_default_dir ()
38 for (int i=0; i < encompass_arr_.size (); i ++)
40 if (encompass_arr_[i]->dir_ < 0)
49 Slur::do_add_processing ()
51 set_bounds (LEFT, encompass_arr_[0]);
52 if (encompass_arr_.size () > 1)
53 set_bounds (RIGHT, encompass_arr_.top ());
57 Slur::do_pre_processing ()
59 // don't set directions
63 Slur::do_substitute_dependency (Score_elem*o, Score_elem*n)
66 while ((i = encompass_arr_.find_i ((Note_column*)o->item ())) >=0)
69 encompass_arr_[i] = (Note_column*)n->item ();
71 encompass_arr_.del (i);
76 Note_column_compare (Note_column *const&n1 , Note_column* const&n2)
78 return Item::left_right_compare (n1, n2);
82 Slur::do_post_processing ()
84 encompass_arr_.sort (Note_column_compare);
87 Real interline_f = paper ()->interline_f ();
88 Real inter_f = interline_f / 2;
91 [OSU]: slur and tie placement
94 * x = centre of head (upside-down: inner raakpunt stem) - d * gap
96 * y = length < 5ss : horizontal raakpunt + d * 0.25 ss
97 y = length >= 5ss : y next interline - d * 0.25 ss
98 --> height <= 5 length ?? we use <= 3 length, now...
100 * suggested gap = ss / 5;
102 // jcn: 1/5 seems so small?
103 Real gap_f = interline_f / 2; // 5;
105 Drul_array<Note_column*> extrema;
106 extrema[LEFT] = encompass_arr_[0];
107 extrema[RIGHT] = encompass_arr_.top ();
110 Real nw_f = paper ()->note_width ();
114 if (extrema[d] != spanned_drul_[d])
117 *(spanned_drul_[d]->width ().length () -0.5*nw_f);
119 else if (extrema[d]->stem_l_ && !extrema[d]->stem_l_->transparent_b_)
121 dy_f_drul_[d] = (int)rint (extrema[d]->stem_l_->height ()[dir_]);
122 /* normal slur from notehead centre to notehead centre, minus gap */
123 dx_f_drul_[d] += -d * gap_f;
127 dy_f_drul_[d] = (int)rint (extrema[d]->head_positions_interval ()[dir_])* inter_f;
129 dy_f_drul_[d] += dir_ * interline_f;
131 while (flip(&d) != LEFT);
135 pos_correct (Real x, Real dx, Real dy)
138 guess how much we can safely increase 'h'
139 parameter of bow without taking too large
141 empiric computer science
143 // return (1.0 + 2.0 * x / dx) / 4.0;
148 Slur::height_f () const
150 Real interline = paper ()->interline_f ();
151 Real notewidth = paper ()->note_width ();
152 Real internote = interline / 2;
155 having the correct (i.e. exactly the same as the ps stuff)
156 x,y coordinates is essential.
157 getting them is quite a mess, currently.
160 Stem* left_stem =encompass_arr_[0]->stem_l_;
161 Real left_x = left_stem->hpos_f ();
162 // ugh, do bow corrections (see brew_mol)
163 left_x += dx_f_drul_[LEFT] + 0.5 * notewidth;
165 // Real left_y = left_stem->dir_ == dir_ ? left_stem->stem_end_f () + dir_
166 // : left_stem->stem_begin_f () + 0.5 * dir_;
167 // left_y *= internote;
168 // ugh, do bow corrections (see brew_mol)
169 // left_y = dy_f_drul_[LEFT];
171 // ugh, do bow corrections (see brew_mol)
172 Real left_y = dy_f_drul_[LEFT];
174 // ugh, where does this asymmetry come from?
176 left_y -= dir_ * internote;
178 Real dx = width ().length ();
179 Real dy = (dy_f_drul_[RIGHT] - dy_f_drul_[LEFT]);
180 Real centre_x = dx / 2;
183 // ugh, need staffheight for bow damping
184 Bezier_bow b (paper ());
186 if (check_debug && !monitor->silent_b ("Slur"))
188 cout << "*****************" << endl;
189 cout << "dir: " << (int)dir_ << endl;
190 cout << "dx: " << dx << endl;
191 cout << "dy: " << dy << endl;
192 cout << "centre: " << centre_x << endl;
193 for (int i = 0; i < encompass_arr_.size (); i++)
194 cout << "i: " << i << " x: "
195 << encompass_arr_[i]->stem_l_->hpos_f () - left_x << endl;
203 b.calc (dx, dy, height, dir_);
205 if (check_debug && !monitor->silent_b ("Slur"))
206 cout << "----" << endl;
207 for (int i = 1; i < encompass_arr_.size () - 1; i++)
209 Stem* stem = encompass_arr_[i]->stem_l_;
211 set x to middle of notehead or on exact x position of stem,
212 according to slur direction
214 Real x = stem->hpos_f () - left_x + notewidth / 2;
215 if (stem->dir_ != dir_)
217 else if (stem->dir_ == UP)
219 Real y = stem->dir_ == dir_ ? stem->stem_end_f ()
220 : stem->stem_begin_f () + 1.5 * dir_;
223 leave a gap: slur mustn't touch head/stem
229 Real shift = dir_ * (y - b.y (x));
231 if (check_debug && !monitor->silent_b ("Slur"))
233 cout << "x: " << x << " (" << abs (centre_x - x) << ")" << endl;
234 cout << "y: " << y << ", curve: " << b.y (x) << endl;
235 cout << "shift: " << shift << endl;
238 if (shift > 0.1 * internote)
239 dh = dh >? shift * pos_correct (abs (centre_x - x), dx, dy);
246 IMPLEMENT_IS_TYPE_B1(Slur,Spanner);