2 slur.cc -- implement external interface for Slur
4 source file of the GNU LilyPond music typesetter
6 (c) 1996--2005 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 Jan Nieuwenhuizen <janneke@gnu.org>
16 #include "directional-element-interface.hh"
17 #include "font-interface.hh"
18 #include "pointer-group-interface.hh"
20 #include "main.hh" // DEBUG_SLUR_SCORING
21 #include "note-column.hh"
22 #include "output-def.hh"
24 #include "staff-symbol-referencer.hh"
25 #include "staff-symbol.hh"
27 #include "text-interface.hh"
29 #include "slur-scoring.hh"
32 get_default_dir (Grob
*me
)
34 extract_grob_set (me
, "note-columns", encompasses
);
37 for (int i
= 0; i
< encompasses
.size (); i
++)
39 if (Note_column::dir (encompasses
[i
]) < 0)
48 MAKE_SCHEME_CALLBACK (Slur
, height
, 2);
50 Slur::height (SCM smob
, SCM ax
)
52 Axis a
= (Axis
)scm_to_int (ax
);
53 Grob
*me
= unsmob_grob (smob
);
56 SCM mol
= me
->get_uncached_stencil ();
58 if (Stencil
*m
= unsmob_stencil (mol
))
60 return ly_interval2scm (ext
);
64 Ugh should have dash-length + dash-period
66 MAKE_SCHEME_CALLBACK (Slur
, print
, 1);
68 Slur::print (SCM smob
)
70 Grob
*me
= unsmob_grob (smob
);
71 extract_grob_set (me
, "note-columns", encompasses
);
72 if (encompasses
.is_empty ())
78 Real staff_thick
= Staff_symbol_referencer::line_thickness (me
);
79 Real base_thick
= robust_scm2double (me
->get_property ("thickness"), 1);
80 Real thick
= base_thick
* staff_thick
;
81 Bezier one
= get_curve (me
);
85 TODO: replace dashed with generic property.
87 SCM p
= me
->get_property ("dash-period");
88 SCM f
= me
->get_property ("dash-fraction");
89 if (scm_is_number (p
) && scm_is_number (f
))
90 a
= Lookup::dashed_slur (one
, thick
, robust_scm2double (p
, 1.0),
91 robust_scm2double (f
, 0));
93 a
= Lookup::slur (one
,
94 get_grob_direction (me
) * staff_thick
* 1.0,
97 #if DEBUG_SLUR_SCORING
98 SCM quant_score
= me
->get_property ("quant-score");
100 if (to_boolean (me
->get_layout ()
101 ->lookup_variable (ly_symbol2scm ("debug-slur-scoring")))
102 && scm_is_string (quant_score
))
105 SCM properties
= Font_interface::text_font_alist_chain (me
);
107 Stencil tm
= *unsmob_stencil (Text_interface::interpret_markup
108 (me
->get_layout ()->self_scm (), properties
,
110 a
.add_at_edge (Y_AXIS
, get_grob_direction (me
), tm
, 1.0, 0);
114 return a
.smobbed_copy ();
118 Slur::get_curve (Grob
*me
)
122 for (SCM s
= me
->get_property ("control-points"); s
!= SCM_EOL
;
124 b
.control_
[i
++] = ly_scm2offset (scm_car (s
));
130 Slur::add_column (Grob
*me
, Grob
*n
)
132 Pointer_group_interface::add_grob (me
, ly_symbol2scm ("note-columns"), n
);
133 add_bound_item (dynamic_cast<Spanner
*> (me
), dynamic_cast<Item
*> (n
));
137 Slur::add_extra_encompass (Grob
*me
, Grob
*n
)
139 Pointer_group_interface::add_grob (me
, ly_symbol2scm ("encompass-objects"), n
);
140 me
->add_dependency (n
);
143 #include "script-interface.hh"
144 MAKE_SCHEME_CALLBACK (Slur
, outside_slur_callback
, 2);
146 Slur::outside_slur_callback (SCM grob
, SCM axis
)
148 Grob
*script
= unsmob_grob (grob
);
149 Axis a
= Axis (scm_to_int (axis
));
151 assert (a
== Y_AXIS
);
153 Grob
*slur
= unsmob_grob (script
->get_object ("slur"));
156 return scm_from_int (0);
158 Direction dir
= get_grob_direction (script
);
160 return scm_from_int (0);
162 /* FIXME: this dependency should be automatic. */
163 if (scm_ilength (slur
->get_property ("control-points")) < 4)
164 Slur::after_line_breaking (slur
->self_scm ());
166 Grob
*cx
= script
->common_refpoint (slur
, X_AXIS
);
167 Grob
*cy
= script
->common_refpoint (slur
, Y_AXIS
);
169 Bezier curve
= Slur::get_curve (slur
);
171 curve
.translate (Offset (slur
->relative_coordinate (cx
, X_AXIS
),
172 slur
->relative_coordinate (cy
, Y_AXIS
)));
174 Interval yext
= robust_relative_extent (script
, cy
, Y_AXIS
);
175 Interval xext
= robust_relative_extent (script
, cx
, X_AXIS
);
177 /* FIXME: slur property, script property? */
178 Real slur_padding
= robust_scm2double (script
->get_property ("slur-padding"),
180 yext
.widen (slur_padding
);
183 Interval
bezext (curve
.control_
[0][X_AXIS
], curve
.control_
[3][X_AXIS
]);
184 bool consider
[] = { false, false, false };
185 Real ys
[] = {0, 0, 0};
186 bool do_shift
= false;
188 for (int d
= LEFT
, k
= 0; d
<= RIGHT
; d
++, k
++)
190 Real x
= xext
.linear_combination ((Direction
) d
);
191 consider
[k
] = bezext
.contains (x
);
196 = (fabs (bezext
[LEFT
] - x
) < EPS
)
197 ? curve
.control_
[0][Y_AXIS
]
198 : ((fabs (bezext
[RIGHT
] - x
) < EPS
)
199 ? curve
.control_
[3][Y_AXIS
]
200 : curve
.get_other_coordinate (X_AXIS
, x
));
203 /* Request shift if slur is contained script's Y, or if
204 script is fully inside slur. */
205 if (yext
.contains (ys
[k
]) || dir
* ys
[k
] > dir
* yext
[-dir
])
212 for (int d
= LEFT
, k
= 0; d
<= RIGHT
; d
++, k
++)
213 offset
= dir
* (max (dir
* offset
,
214 dir
* (ys
[k
] - yext
[-dir
] + dir
* slur_padding
)));
217 return scm_from_double (offset
);
220 MAKE_SCHEME_CALLBACK (Slur
, after_line_breaking
, 1);
222 Slur::after_line_breaking (SCM smob
)
224 Spanner
*me
= dynamic_cast<Spanner
*> (unsmob_grob (smob
));
225 extract_grob_set (me
, "note-columns", encompasses
);
226 if (encompasses
.is_empty ())
229 return SCM_UNSPECIFIED
;
232 if (!get_grob_direction (me
))
233 set_grob_direction (me
, get_default_dir (me
));
235 if (scm_ilength (me
->get_property ("control-points")) < 4)
236 set_slur_control_points (me
);
238 return SCM_UNSPECIFIED
;
241 ADD_INTERFACE (Slur
, "slur-interface",
243 "positions quant-score eccentricity encompass-objects control-points dash-period dash-fraction slur-details direction height-limit note-columns ratio thickness");