lilypond-1.5.9
[lilypond.git] / lily / bow.cc
blob2fbb65d3091af6fdf0e5e5bfa01ca33414b8b585
1 /*
2 bow.cc -- implement Bow
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--1999 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 Jan Nieuwenhuizen <janneke@gnu.org>
8 */
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"
20 Bow::Bow ()
22 dy_f_drul_[LEFT] = dy_f_drul_[RIGHT] = 0.0;
23 dx_f_drul_[LEFT] = dx_f_drul_[RIGHT] = 0.0;
26 Molecule*
27 Bow::do_brew_molecule_p () const
29 Real thick = paper_l ()->get_var ("slur_thickness");
30 Bezier one = get_curve ();
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);
39 return new Molecule (a);
42 Offset
43 Bow::center () const
45 Real dy = dy_f_drul_[RIGHT] - dy_f_drul_[LEFT];
46 Real dx = extent(X_AXIS).length ();
48 return Offset (dx / 2, dy);
52 Interval
53 Bow::curve_extent (Axis a) const
55 return get_curve ().extent (a);
58 Bezier
59 Bow::get_curve () const
61 Bezier_bow b (get_encompass_offset_arr (), directional_element (this).get ());
63 b.ratio_ = paper_l ()->get_var ("slur_ratio");
64 b.height_limit_ = paper_l ()->get_var ("slur_height_limit");
65 b.rc_factor_ = paper_l ()->get_var ("slur_rc_factor");
67 b.calculate ();
68 return b.get_curve ();
71 #if 0
74 TODO: FIXME.
78 Clipping
80 This function tries to address two issues:
81 * the tangents of the slur should always point inwards
82 in the actual slur, i.e. *after rotating back*.
84 * slurs shouldn't be too high
85 let's try : h <= 1.2 b && h <= 3 staffheight?
87 We could calculate the tangent of the bezier curve from
88 both ends going inward, and clip the slur at the point
89 where the tangent (after rotation) points up (or inward
90 with a certain maximum angle).
92 However, we assume that real clipping is not the best
93 answer. We expect that moving the outer control point up
94 if the slur becomes too high will result in a nicer slur
95 after recalculation.
97 Knowing that the tangent is the line through the first
98 two control points, we'll clip (move the outer control
99 point upwards) too if the tangent points outwards.
102 bool
103 Bezier_bow::calc_clipping ()
105 Real clip_height = paper_l_->get_var ("slur_clip_height");
106 Real clip_ratio = paper_l_->get_var ("slur_clip_ratio");
107 Real clip_angle = paper_l_->get_var ("slur_clip_angle");
109 Real b = curve_.control_[3][X_AXIS] - curve_.control_[0][X_AXIS];
110 Real clip_h = clip_ratio * b <? clip_height;
111 Real begin_h = curve_.control_[1][Y_AXIS] - curve_.control_[0][Y_AXIS];
112 Real end_h = curve_.control_[2][Y_AXIS] - curve_.control_[3][Y_AXIS];
113 Real begin_dy = 0 >? begin_h - clip_h;
114 Real end_dy = 0 >? end_h - clip_h;
116 Real pi = M_PI;
117 Real begin_alpha = (curve_.control_[1] - curve_.control_[0]).arg () + dir_ * alpha_;
118 Real end_alpha = pi - (curve_.control_[2] - curve_.control_[3]).arg () - dir_ * alpha_;
120 Real max_alpha = clip_angle / 90 * pi / 2;
121 if ((begin_dy < 0) && (end_dy < 0)
122 && (begin_alpha < max_alpha) && (end_alpha < max_alpha))
123 return false;
125 transform_back ();
127 if ((begin_dy > 0) || (end_dy > 0))
129 Real dy = (begin_dy + end_dy) / 4;
130 dy *= cos (alpha_);
131 encompass_[0][Y_AXIS] += dir_ * dy;
132 encompass_.top ()[Y_AXIS] += dir_ * dy;
134 else
136 //ugh
137 Real c = 0.4;
138 if (begin_alpha >= max_alpha)
139 begin_dy = 0 >? c * begin_alpha / max_alpha * begin_h;
140 if (end_alpha >= max_alpha)
141 end_dy = 0 >? c * end_alpha / max_alpha * end_h;
143 encompass_[0][Y_AXIS] += dir_ * begin_dy;
144 encompass_.top ()[Y_AXIS] += dir_ * end_dy;
146 Offset delta = encompass_.top () - encompass_[0];
147 alpha_ = delta.arg ();
150 to_canonic_form ();
152 return true;
154 #endif
158 Array<Offset>
159 Bow::get_encompass_offset_arr () const
161 Array<Offset> offset_arr;
162 offset_arr.push (Offset (dx_f_drul_[LEFT], dy_f_drul_[LEFT]));
163 offset_arr.push (Offset (spanner_length () + dx_f_drul_[RIGHT],
164 dy_f_drul_[RIGHT]));
166 return offset_arr;