Real
Beam::get_beam_translation (Grob *me)
{
- SCM func = me->get_property ("space-function");
+ int beam_count = get_beam_count (me);
+ Real staff_space = Staff_symbol_referencer::staff_space (me);
+ Real line = Staff_symbol_referencer::line_thickness (me);
+ Real thickness = get_thickness (me);
+ Real fract = robust_scm2double (me->get_property ("length-fraction"), 1.0);
+
+ Real beam_translation = beam_count < 4
+ ? (2 * staff_space + line - thickness) / 2.0
+ : (3 * staff_space + line - thickness) / 3.0;
- if (ly_is_procedure (func))
- {
- SCM s = scm_call_2 (func, me->self_scm (), scm_from_int (get_beam_count (me)));
- return scm_to_double (s);
- }
- else
- return 0.81;
+ return fract * beam_translation;
}
/* Maximum beam_count. */
return m;
}
-/*
- Space return space between beams.
-*/
-MAKE_SCHEME_CALLBACK (Beam, space_function, 2);
-SCM
-Beam::space_function (SCM smob, SCM beam_count)
-{
- Grob *me = unsmob_grob (smob);
-
- Real staff_space = Staff_symbol_referencer::staff_space (me);
- Real line = Staff_symbol_referencer::line_thickness (me);
- Real thickness = get_thickness (me);
-
- Real beam_translation = scm_to_int (beam_count) < 4
- ? (2 * staff_space + line - thickness) / 2.0
- : (3 * staff_space + line - thickness) / 3.0;
-
- return scm_from_double (beam_translation);
-}
/* After pre-processing all directions should be set.
Several post-processing routines (stem, slur, script) need stem/beam
For a beam that only has one stem, we try to do some disappearance magic:
we revert the flag, and move on to The Eternal Engraving Fields. */
+ Direction d = CENTER;
+
int count = visible_stem_count (me);
if (count < 2)
{
me->suicide ();
return SCM_UNSPECIFIED;
}
+ else
+ {
+ /*
+ ugh.
+
+ can happen in stem-tremolo case.
+ TODO: fixme.
+ */
+ d = Stem::get_default_dir (stems[0]);
+ }
}
- Direction d = CENTER;
if (count >= 1)
{
d = get_default_dir (me);
consider_auto_knees (me);
- set_stem_directions (me, d);
+ }
+ if (d)
+ {
+ set_stem_directions (me, d);
connect_beams (me);
-
set_stem_shorten (me);
}
-
+
return scm_from_int (d);
}
if (stem)
{
int t = Stem::duration_log (stem);
-
- SCM proc = me->get_property ("flag-width-function");
- SCM result = scm_call_1 (proc, scm_from_int (t));
- nw_f = scm_to_double (result);
+ // ugh. hardcoded.
+ if (t == 1)
+ nw_f = 1.98;
+ else
+ nw_f = 1.32;
}
else
nw_f = break_overshoot[RIGHT] / 2;
Direction stem_dir = stems.size () ? to_dir (stems[0]->get_property ("direction")) : UP;
- Stencil tm = *unsmob_stencil (Text_interface::interpret_markup
+ Stencil score = *unsmob_stencil (Text_interface::interpret_markup
(me->get_layout ()->self_scm (), properties, quant_score));
- the_beam.add_at_edge (Y_AXIS, stem_dir, tm, 1.0, 0);
+
+ if (!score.is_empty ())
+ the_beam.add_at_edge (Y_AXIS, stem_dir, score, 1.0, 0);
}
#endif
}
}
- SCM func = me->get_property ("dir-function");
- SCM s = scm_call_2 (func,
- scm_cons (scm_from_int (count[UP]),
- scm_from_int (count[DOWN])),
- scm_cons (scm_from_int (total[UP]),
- scm_from_int (total[DOWN])));
-
- if (scm_is_number (s) && scm_to_int (s))
- return to_dir (s);
-
- /* If dir is not determined: get default */
- return to_dir (me->get_property ("neutral-direction"));
+ Direction dir = CENTER;
+
+ if (Direction d = (Direction) sign (count[UP] - count[DOWN]))
+ dir = d;
+ else if (Direction d = (Direction) sign (total[UP] / count[UP] - total[DOWN]/count[DOWN]))
+ dir = d;
+ else if (Direction d = (Direction) sign (total[UP] - total[DOWN]))
+ dir = d;
+ else
+ dir = to_dir (me->get_property ("neutral-direction"));
+
+ return dir;
}
/* Set all stems with non-forced direction to beam direction.
for (SCM i = callbacks; scm_is_pair (i); i = scm_cdr (i))
scm_call_1 (scm_car (i), me->self_scm ());
- /*
- TODO: move this in separate calc function.
- */
- set_stem_lengths (me);
return SCM_UNSPECIFIED;
}
+
void
set_minimum_dy (Grob *me, Real *dy)
{
}
/*
- Compute a first approximation to the beam slope.
+ Compute a first approximation to the beam slope.
*/
-MAKE_SCHEME_CALLBACK (Beam, least_squares, 1);
+MAKE_SCHEME_CALLBACK (Beam, calc_least_squares_positions, 2);
SCM
-Beam::least_squares (SCM smob)
+Beam::calc_least_squares_positions (SCM smob, SCM posns)
{
+ (void) posns;
+
Grob *me = unsmob_grob (smob);
int count = visible_stem_count (me);
Interval pos (0, 0);
- if (count < 1)
- {
- me->set_property ("positions", ly_interval2scm (pos));
- return SCM_UNSPECIFIED;
- }
-
Array<Real> x_posns;
extract_grob_set (me, "stems", stems);
Grob *commonx = common_refpoint_of_array (stems, me, X_AXIS);
Real y = 0;
Real slope = 0;
Real dy = 0;
-
+ Real ldy = 0.0;
if (!ideal.delta ())
{
Interval chord (Stem::chord_start_y (first_visible_stem (me)),
slope esp. of the first part of a broken beam should predict
where the second part goes.
*/
- me->set_property ("least-squares-dy",
- scm_from_double (pos[RIGHT] - pos[LEFT]));
+ ldy = pos[RIGHT] - pos[LEFT];
}
else
{
dy = slope * dx;
set_minimum_dy (me, &dy);
- me->set_property ("least-squares-dy", scm_from_double (dy));
+
+ ldy = dy;
pos = Interval (y, (y + dy));
}
*/
scale_drul (&pos, 1 / Staff_symbol_referencer::staff_space (me));
- me->set_property ("positions", ly_interval2scm (pos));
-
- return SCM_UNSPECIFIED;
+ me->set_property ("least-squares-dy", scm_from_double (ldy));
+ return ly_interval2scm (pos);
}
/*
TODO: we should use the concaveness to control the amount of damping
applied.
*/
-MAKE_SCHEME_CALLBACK (Beam, shift_region_to_valid, 1);
+MAKE_SCHEME_CALLBACK (Beam, shift_region_to_valid, 2);
SCM
-Beam::shift_region_to_valid (SCM grob)
+Beam::shift_region_to_valid (SCM grob, SCM posns)
{
Grob *me = unsmob_grob (grob);
/*
Grob *fvs = first_visible_stem (me);
if (!fvs)
- return SCM_UNSPECIFIED;
+ return posns;
Real x0 = fvs->relative_coordinate (commonx, X_AXIS);
for (int i = 0; i < stems.size (); i++)
Grob *lvs = last_visible_stem (me);
if (!lvs)
- return SCM_UNSPECIFIED;
+ return posns;
Real dx = lvs->relative_coordinate (commonx, X_AXIS) - x0;
- Drul_array<Real> pos = ly_scm2interval (me->get_property ("positions"));
+ Drul_array<Real> pos = ly_scm2interval (posns);
+
scale_drul (&pos, Staff_symbol_referencer::staff_space (me));
pos = Drul_array<Real> (y, (y + dy));
scale_drul (&pos, 1 / Staff_symbol_referencer::staff_space (me));
- me->set_property ("positions", ly_interval2scm (pos));
- return SCM_UNSPECIFIED;
+ return ly_interval2scm (pos);
}
/* This neat trick is by Werner Lemberg,
damped = tanh (slope)
corresponds with some tables in [Wanske] CHECKME */
-MAKE_SCHEME_CALLBACK (Beam, slope_damping, 1);
+MAKE_SCHEME_CALLBACK (Beam, slope_damping, 2);
SCM
-Beam::slope_damping (SCM smob)
+Beam::slope_damping (SCM smob, SCM posns)
{
Grob *me = unsmob_grob (smob);
+ Drul_array<Real> pos = ly_scm2interval (posns);
if (visible_stem_count (me) <= 1)
return SCM_UNSPECIFIED;
+
SCM s = me->get_property ("damping");
Real damping = scm_to_double (s);
-
+ Real concaveness = robust_scm2double (me->get_property ("concaveness"), 0.0);
+ if (concaveness >= 10000)
+ {
+ pos[LEFT] = pos[RIGHT];
+ me->set_property ("least-squares-dy", scm_from_double (0));
+ damping = 0;
+ }
+
if (damping)
{
- Drul_array<Real> pos = ly_scm2interval (me->get_property ("positions"));
scale_drul (&pos, Staff_symbol_referencer::staff_space (me));
Real dy = pos[RIGHT] - pos[LEFT];
Real slope = dy && dx ? dy / dx : 0;
- Real concaveness = robust_scm2double (me->get_property ("concaveness"), 0.0);
-
slope = 0.6 * tanh (slope) / (damping + concaveness);
Real damped_dy = slope * dx;
pos[RIGHT] -= (dy - damped_dy) / 2;
scale_drul (&pos, 1 / Staff_symbol_referencer::staff_space (me));
-
- me->set_property ("positions", ly_interval2scm (pos));
}
- return SCM_UNSPECIFIED;
+
+ return ly_interval2scm (pos);
}
/*
Hmm. At this time, beam position and slope are determined. Maybe,
stem directions and length should set to relative to the chord's
position of the beam. */
-void
-Beam::set_stem_lengths (Grob *me)
+MAKE_SCHEME_CALLBACK(Beam, set_stem_lengths, 2);
+SCM
+Beam::set_stem_lengths (SCM smob, SCM posns)
{
+ Grob *me = unsmob_grob (smob);
+
extract_grob_set (me, "stems", stems);
if (!stems.size ())
- return;
+ return posns;
Grob *common[2];
for (int a = 2; a--;)
common[a] = common_refpoint_of_array (stems, me, Axis (a));
- Drul_array<Real> pos = ly_scm2realdrul (me->get_property ("positions"));
+ Drul_array<Real> pos = ly_scm2realdrul (posns);
Real staff_space = Staff_symbol_referencer::staff_space (me);
scale_drul (&pos, staff_space);
Stem::set_stemend (s, 2 * stem_y / staff_space);
}
+
+ return posns;
}
void
"damping "
"details "
"direction "
- "dir-function "
- "flag-width-function "
"gap "
"gap-count "
"inspect-quants "
"knee "
+ "length-fraction "
"least-squares-dy "
"neutral-direction "
"position-callbacks "
"positions "
"quant-score "
"shorten "
- "space-function "
+ "stems "
"thickness "
);