lilypond-0.1.51
[lilypond.git] / lily / slur.cc
blob88b2c6cc3378661071b2dd6b018bdaac21e8e447
1 /*
2 slur.cc -- implement Slur
4 source file of the GNU LilyPond music typesetter
6 (c) 1996, 1997 Han-Wen Nienhuys <hanwen@stack.nl>
7 */
9 /*
10 TODO:
12 think about crossing stems.
13 Begin and end should be treated as a Script.
15 #include "slur.hh"
16 #include "scalar.hh"
17 #include "lookup.hh"
18 #include "paper-def.hh"
19 #include "note-column.hh"
20 #include "stem.hh"
21 #include "p-col.hh"
22 #include "molecule.hh"
23 #include "debug.hh"
24 #include "boxes.hh"
26 void
27 Slur::add (Note_column*n)
29 encompass_arr_.push (n);
30 add_dependency (n);
33 void
34 Slur::set_default_dir ()
36 dir_ = DOWN;
37 for (int i=0; i < encompass_arr_.size (); i ++)
39 if (encompass_arr_[i]->dir_ < 0)
41 dir_ = UP;
42 break;
47 void
48 Slur::do_add_processing ()
50 set_bounds (LEFT, encompass_arr_[0]);
51 if (encompass_arr_.size () > 1)
52 set_bounds (RIGHT, encompass_arr_.top ());
55 void
56 Slur::do_pre_processing ()
58 // don't set directions
61 void
62 Slur::do_substitute_dependency (Score_elem*o, Score_elem*n)
64 int i;
65 while ((i = encompass_arr_.find_i ((Note_column*)o->item ())) >=0)
67 if (n)
68 encompass_arr_[i] = (Note_column*)n->item ();
69 else
70 encompass_arr_.del (i);
74 static int
75 Note_column_compare (Note_column *const&n1 , Note_column* const&n2)
77 return Item::left_right_compare (n1, n2);
80 void
81 Slur::do_post_processing ()
83 encompass_arr_.sort (Note_column_compare);
84 if (!dir_)
85 set_default_dir ();
86 Real interline_f = paper ()->interline_f ();
87 Real inter_f = interline_f / 2;
89 /*
90 [OSU]: slur and tie placement
92 slurs:
93 * x = centre of head (upside-down: inner raakpunt stem) - d * gap
95 * y = length < 5ss : horizontal raakpunt + d * 0.25 ss
96 y = length >= 5ss : y next interline - d * 0.25 ss
97 --> height <= 5 length ?? we use <= 3 length, now...
99 * suggested gap = ss / 5;
101 // jcn: 1/5 seems so small?
102 Real gap_f = interline_f / 2; // 5;
104 Drul_array<Note_column*> extrema;
105 extrema[LEFT] = encompass_arr_[0];
106 extrema[RIGHT] = encompass_arr_.top ();
108 Direction d=LEFT;
109 Real nw_f = paper ()->note_width ();
113 if (extrema[d] != spanned_drul_[d])
115 dx_f_drul_[d] = -d
116 *(spanned_drul_[d]->width ().length () -0.5*nw_f);
118 else if (extrema[d]->stem_l_ && !extrema[d]->stem_l_->transparent_b_)
120 dy_f_drul_[d] = (int)rint (extrema[d]->stem_l_->height ()[dir_]);
121 /* normal slur from notehead centre to notehead centre, minus gap */
122 dx_f_drul_[d] += -d * gap_f;
124 else
126 dy_f_drul_[d] = (int)rint (extrema[d]->head_positions_interval ()[dir_])* inter_f;
128 dy_f_drul_[d] += dir_ * interline_f;
130 while ((d *= -1) != LEFT);
133 Real
134 Slur::height_f () const
137 rather braindead way that of adjusting slur height
138 for heads/stems that extend beyond default slur
139 works quite good
142 Real interline_f = paper ()->interline_f ();
143 Real nh_f = interline_f / 2;
144 Real h = 0;
145 Real dx = width ().length ();
146 Real dy = dy_f_drul_[RIGHT] - dy_f_drul_[LEFT];
147 Stem* stem = encompass_arr_[0]->stem_l_;
148 Real lx = stem->hpos_f ();
149 Real centre = (width ().min () + width ().max ()) / 2;
150 Real ly = stem->dir_ == dir_ ? stem->stem_end_f () : stem->stem_begin_f ()
151 + dir_ * nh_f / 2;
152 for (int i = 0; i < encompass_arr_.size (); i++)
154 Stem* stem = encompass_arr_[i]->stem_l_;
155 Real sx = abs (centre - stem->hpos_f ());
156 Real sy = stem->dir_ == dir_ ? stem->stem_end_f ()
157 : stem->stem_begin_f () + dir_ * nh_f / 2;
158 sy = dir_ * (sy - (ly + ((stem->hpos_f () - lx) / dx) * dy));
160 uhm, correct for guess bezier curve (more if further from centre)
161 forget the cos alpha...
163 if (sy > 0)
164 h = h >? sy * (1 + 2 * sx / dx);
166 Real ratio = 1.0/3; // duh
168 correct h for slur ratio
170 Real staffheight = paper ()->get_var ("barsize");
171 if (h)
172 h *= ((h * interline_f) / dx ) / ratio;
173 return h;
176 IMPLEMENT_IS_TYPE_B1(Slur,Spanner);