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>
10 #include "dimension-cache.hh"
13 #include "paper-def.hh"
14 #include "molecule.hh"
16 #include "bezier-bow.hh"
18 #include "directional-element-interface.hh"
22 dy_f_drul_
[LEFT
] = dy_f_drul_
[RIGHT
] = 0.0;
23 dx_f_drul_
[LEFT
] = dx_f_drul_
[RIGHT
] = 0.0;
27 Bow::do_brew_molecule_p () const
29 Real thick
= paper_l ()->get_var ("slur_thickness");
30 Bezier one
= get_curve ();
33 SCM d
= get_elt_property ("dashed");
35 a
= lookup_l ()->dashed_slur (one
, thick
, gh_scm2int (d
));
37 a
= lookup_l ()->slur (one
, directional_element (this).get () * thick
, thick
);
39 return new Molecule (a
);
45 Real dy
= dy_f_drul_
[RIGHT
] - dy_f_drul_
[LEFT
];
46 Real dx
= extent(X_AXIS
).length ();
48 return Offset (dx
/ 2, dy
);
53 Bow::curve_extent (Axis a
) const
55 return get_curve ().extent (a
);
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");
68 return b
.get_curve ();
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
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.
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
;
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
))
127 if ((begin_dy
> 0) || (end_dy
> 0))
129 Real dy
= (begin_dy
+ end_dy
) / 4;
131 encompass_
[0][Y_AXIS
] += dir_
* dy
;
132 encompass_
.top ()[Y_AXIS
] += dir_
* dy
;
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 ();
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
],