source file of the GNU LilyPond music typesetter
- (c) 1996--2005 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+ (c) 1996--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
Jan Nieuwenhuizen <janneke@gnu.org>
*/
#include "slur.hh"
-#include <math.h>
#include "beam.hh"
#include "bezier.hh"
#include "warn.hh"
#include "slur-scoring.hh"
-MAKE_SCHEME_CALLBACK (Slur, height, 2);
+#include "script-interface.hh"
+
+
+
+MAKE_SCHEME_CALLBACK(Slur, calc_direction, 1)
SCM
-Slur::height (SCM smob, SCM ax)
+Slur::calc_direction (SCM smob)
{
- Axis a = (Axis)scm_to_int (ax);
Grob *me = unsmob_grob (smob);
- assert (a == Y_AXIS);
+ extract_grob_set (me, "note-columns", encompasses);
- SCM mol = me->get_uncached_stencil ();
- Interval ext;
- if (Stencil *m = unsmob_stencil (mol))
- ext = m->extent (a);
- return ly_interval2scm (ext);
+ if (encompasses.is_empty ())
+ {
+ me->suicide ();
+ return SCM_BOOL_F;
+ }
+
+ Direction d = DOWN;
+ for (int i = 0; i < encompasses.size (); i++)
+ {
+ if (Note_column::dir (encompasses[i]) < 0)
+ {
+ d = UP;
+ break;
+ }
+ }
+ return scm_from_int (d);
+}
+
+MAKE_SCHEME_CALLBACK (Slur, height, 1);
+SCM
+Slur::height (SCM smob)
+{
+ Grob *me = unsmob_grob (smob);
+
+ // FIXME uncached
+ Stencil *m = me->get_stencil ();
+ return m ? ly_interval2scm (m->extent (Y_AXIS)) : ly_interval2scm (Interval ());
}
/*
#if DEBUG_SLUR_SCORING
SCM quant_score = me->get_property ("quant-score");
- if (to_boolean (me->get_layout ()
+ if (to_boolean (me->layout ()
->lookup_variable (ly_symbol2scm ("debug-slur-scoring")))
&& scm_is_string (quant_score))
{
SCM properties = Font_interface::text_font_alist_chain (me);
Stencil tm = *unsmob_stencil (Text_interface::interpret_markup
- (me->get_layout ()->self_scm (), properties,
+ (me->layout ()->self_scm (), properties,
quant_score));
a.add_at_edge (Y_AXIS, get_grob_direction (me), tm, 1.0, 0);
}
Slur::add_extra_encompass (Grob *me, Grob *n)
{
Pointer_group_interface::add_grob (me, ly_symbol2scm ("encompass-objects"), n);
- me->add_dependency (n);
}
+
MAKE_SCHEME_CALLBACK (Slur, outside_slur_callback, 2);
SCM
-Slur::outside_slur_callback (SCM grob, SCM axis)
+Slur::outside_slur_callback (SCM grob, SCM offset_scm)
{
Grob *script = unsmob_grob (grob);
- Axis a = Axis (scm_to_int (axis));
- (void) a;
- assert (a == Y_AXIS);
-
- Grob *slur = unsmob_grob (script->get_object ("slur"));
+ Grob *slur = unsmob_grob (script->get_object ("slur"));
if (!slur)
- return scm_from_int (0);
+ return offset_scm;
+
+ SCM avoid = script->get_property ("avoid-slur");
+ if (avoid != ly_symbol2scm ("outside")
+ && avoid != ly_symbol2scm ("around"))
+ return offset_scm;
+
+ Direction dir = get_grob_direction (script);
+ if (dir == CENTER)
+ return offset_scm;
Grob *cx = script->common_refpoint (slur, X_AXIS);
Grob *cy = script->common_refpoint (slur, Y_AXIS);
Interval yext = robust_relative_extent (script, cy, Y_AXIS);
Interval xext = robust_relative_extent (script, cx, X_AXIS);
+ yext.translate (robust_scm2double (offset_scm, 0));
+
+
+ /* FIXME: slur property, script property? */
Real slur_padding = robust_scm2double (script->get_property ("slur-padding"),
- 0.0); // todo: slur property, script property?
+ 0.0);
yext.widen (slur_padding);
- Real EPS = 1e-3;
-
- Interval bezext (curve.control_[0][X_AXIS],
- curve.control_[3][X_AXIS]);
+ Real EPS = 1e-3;
+ Interval bezext (curve.control_[0][X_AXIS], curve.control_[3][X_AXIS]);
bool consider[] = { false, false, false };
Real ys[] = {0, 0, 0};
- int k = 0;
bool do_shift = false;
-
- for (int d = LEFT; d <= RIGHT; d++)
+
+ for (int d = LEFT, k = 0; d <= RIGHT; d++, k++)
{
Real x = xext.linear_combination ((Direction) d);
consider[k] = bezext.contains (x);
: curve.get_other_coordinate (X_AXIS, x));
consider[k] = true;
- if (yext.contains (ys[k]))
+ /* Request shift if slur is contained script's Y, or if
+ script is inside slur and avoid == outside. */
+ if (yext.contains (ys[k])
+ || (dir * ys[k] > dir * yext[-dir] && avoid == ly_symbol2scm ("outside")))
do_shift = true;
}
}
- Real offset = 0.0;
+
+ Real avoidance_offset = 0.0;
if (do_shift)
{
- k = 0;
- Direction dir = get_grob_direction (script);
- for (int d = LEFT; d <= RIGHT; d++)
- {
- offset = dir * (max (dir * offset,
- dir * (ys[k] - yext[-dir] + dir * slur_padding)));
- k++;
- }
+ for (int d = LEFT, k = 0; d <= RIGHT; d++, k++)
+ avoidance_offset = dir * (max (dir * avoidance_offset,
+ dir * (ys[k] - yext[-dir] + dir * slur_padding)));
}
- return scm_make_real (offset);
+ return scm_from_double (scm_to_double (offset_scm) + avoidance_offset);
}
-static Direction
-get_default_dir (Grob *me)
-{
- extract_grob_set (me, "note-columns", encompasses);
- Direction d = DOWN;
- for (int i = 0; i < encompasses.size (); i++)
- {
- if (Note_column::dir (encompasses[i]) < 0)
- {
- d = UP;
- break;
- }
- }
- return d;
-}
-
-MAKE_SCHEME_CALLBACK (Slur, after_line_breaking, 1);
-SCM
-Slur::after_line_breaking (SCM smob)
-{
- Spanner *me = dynamic_cast<Spanner *> (unsmob_grob (smob));
- extract_grob_set (me, "note-columns", encompasses);
- if (encompasses.is_empty ())
- {
- me->suicide ();
- return SCM_UNSPECIFIED;
- }
-
- if (!get_grob_direction (me))
- set_grob_direction (me, get_default_dir (me));
-
- if (scm_ilength (me->get_property ("control-points")) < 4)
- set_slur_control_points (me);
-
- return SCM_UNSPECIFIED;
-}
ADD_INTERFACE (Slur, "slur-interface",
+
"A slur",
- "positions quant-score eccentricity encompass-objects control-points dash-period dash-fraction slur-details direction height-limit note-columns ratio thickness");
+
+ /* properties */
+ "control-points "
+ "dash-fraction "
+ "dash-period "
+ "direction "
+ "eccentricity "
+ "encompass-objects "
+ "height-limit "
+ "note-columns "
+ "positions "
+ "quant-score "
+ "ratio "
+ "details "
+ "thickness ");