]> git.donarmstrong.com Git - lilypond.git/blob - lily/bow.cc
patch::: 1.3.17.jcn2
[lilypond.git] / lily / bow.cc
1 /*
2   bow.cc -- implement Bow
3
4   source file of the GNU LilyPond music typesetter
5
6   (c)  1997--1999 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7       Jan Nieuwenhuizen <janneke@gnu.org>
8 */
9
10 #include "dimension-cache.hh"
11 #include "bow.hh"
12 #include "debug.hh"
13 #include "paper-def.hh"
14 #include "molecule.hh"
15 #include "lookup.hh"
16 #include "bezier-bow.hh"
17 #include "main.hh"
18 #include "directional-element-interface.hh"
19
20 Bow::Bow ()
21 {
22   dy_f_drul_[LEFT] = dy_f_drul_[RIGHT] = 0.0;
23   dx_f_drul_[LEFT] = dx_f_drul_[RIGHT] = 0.0;
24 }
25
26 Molecule*
27 Bow::do_brew_molecule_p () const
28 {
29   Real thick = paper_l ()->get_var ("slur_thickness");
30   Bezier one = get_curve ();
31
32   Molecule a;
33   SCM d =  get_elt_property ("dashed");
34   if (gh_number_p (d))
35     a = lookup_l ()->dashed_slur (one, thick, gh_scm2int (d));
36   else
37     a = lookup_l ()->slur (one, directional_element (this).get () * thick, thick);
38   
39   return new Molecule (a); 
40 }
41
42 Offset
43 Bow::center () const
44 {
45   Real dy = dy_f_drul_[RIGHT] - dy_f_drul_[LEFT];
46   Real dx =  extent(X_AXIS).length ();
47
48   return Offset (dx / 2, dy);
49 }
50
51
52 Interval
53 Bow::curve_extent (Axis a) const
54 {
55   return get_curve ().extent (a);
56 }
57
58 Bezier
59 Bow::get_curve () const
60 {
61   Bezier_bow b (paper_l (),
62                 get_encompass_offset_arr (), directional_element (this).get ());
63   
64   return b.get_curve ();
65 }
66
67 #if 0
68
69 /*
70   TODO: FIXME.
71  */
72
73 /*
74   Clipping
75
76   This function tries to address two issues:
77     * the tangents of the slur should always point inwards 
78       in the actual slur, i.e.  *after rotating back*.
79
80     * slurs shouldn't be too high 
81       let's try : h <= 1.2 b && h <= 3 staffheight?
82
83   We could calculate the tangent of the bezier curve from
84   both ends going inward, and clip the slur at the point
85   where the tangent (after rotation) points up (or inward
86   with a certain maximum angle).
87   
88   However, we assume that real clipping is not the best
89   answer.  We expect that moving the outer control point up 
90   if the slur becomes too high will result in a nicer slur 
91   after recalculation.
92
93   Knowing that the tangent is the line through the first
94   two control points, we'll clip (move the outer control
95   point upwards) too if the tangent points outwards.
96  */
97
98 bool
99 Bezier_bow::calc_clipping ()
100 {
101   Real clip_height = paper_l_->get_var ("slur_clip_height");
102   Real clip_ratio = paper_l_->get_var ("slur_clip_ratio");
103   Real clip_angle = paper_l_->get_var ("slur_clip_angle");
104
105   Real b = curve_.control_[3][X_AXIS] - curve_.control_[0][X_AXIS];
106   Real clip_h = clip_ratio * b <? clip_height;
107   Real begin_h = curve_.control_[1][Y_AXIS] - curve_.control_[0][Y_AXIS];
108   Real end_h = curve_.control_[2][Y_AXIS] - curve_.control_[3][Y_AXIS];
109   Real begin_dy = 0 >? begin_h - clip_h;
110   Real end_dy = 0 >? end_h - clip_h;
111   
112   Real pi = M_PI;
113   Real begin_alpha = (curve_.control_[1] - curve_.control_[0]).arg () + dir_ * alpha_;
114   Real end_alpha = pi -  (curve_.control_[2] - curve_.control_[3]).arg () - dir_  * alpha_;
115
116   Real max_alpha = clip_angle / 90 * pi / 2;
117   if ((begin_dy < 0) && (end_dy < 0)
118     && (begin_alpha < max_alpha) && (end_alpha < max_alpha))
119     return false;
120
121   transform_back ();
122
123   if ((begin_dy > 0) || (end_dy > 0))
124     {
125       Real dy = (begin_dy + end_dy) / 4;
126       dy *= cos (alpha_);
127       encompass_[0][Y_AXIS] += dir_ * dy;
128       encompass_.top ()[Y_AXIS] += dir_ * dy;
129     }
130   else
131     {
132       //ugh
133       Real c = 0.4;
134       if (begin_alpha >= max_alpha)
135         begin_dy = 0 >? c * begin_alpha / max_alpha * begin_h;
136       if (end_alpha >= max_alpha)
137         end_dy = 0 >? c * end_alpha / max_alpha * end_h;
138
139       encompass_[0][Y_AXIS] += dir_ * begin_dy;
140       encompass_.top ()[Y_AXIS] += dir_ * end_dy;
141
142       Offset delta = encompass_.top () - encompass_[0];
143       alpha_ = delta.arg ();
144     }
145
146   to_canonic_form ();
147
148   return true;
149 }
150 #endif
151
152
153
154 Array<Offset>
155 Bow::get_encompass_offset_arr () const
156 {
157   Array<Offset> offset_arr;
158   offset_arr.push (Offset (dx_f_drul_[LEFT], dy_f_drul_[LEFT]));
159   offset_arr.push (Offset (spanner_length () + dx_f_drul_[RIGHT],
160                            dy_f_drul_[RIGHT]));
161                       
162   return offset_arr;
163 }
164
165