/*
This file is part of LilyPond, the GNU music typesetter.
- Copyright (C) 1997--2012 Han-Wen Nienhuys <hanwen@xs4all.nl>
+ Copyright (C) 1997--2015 Han-Wen Nienhuys <hanwen@xs4all.nl>
Jan Nieuwenhuizen <janneke@gnu.org>
LilyPond is free software: you can redistribute it and/or modify
#include "stencil.hh"
#include "stem.hh"
#include "warn.hh"
+#include "string-convert.hh"
Real
get_detail (SCM alist, SCM sym, Real def)
REGION_SIZE = get_detail (details, ly_symbol2scm ("region-size"), 2);
// forbidden quants
- SECONDARY_BEAM_DEMERIT = get_detail (details, ly_symbol2scm ("secondary-beam-demerit"), 10.0);
+ SECONDARY_BEAM_DEMERIT = get_detail (details, ly_symbol2scm ("secondary-beam-demerit"), 10.0)
+ // For stems that are non-standard, the forbidden beam quanting
+ // doesn't really work, so decrease their importance.
+ * exp(- 8*fabs (1.0 - robust_scm2double(him->get_property ("length-fraction"), 1.0)));
STEM_LENGTH_DEMERIT_FACTOR = get_detail (details, ly_symbol2scm ("stem-length-demerit-factor"), 5);
HORIZONTAL_INTER_QUANT_PENALTY = get_detail (details, ly_symbol2scm ("horizontal-inter-quant"), 500);
// Collisions
COLLISION_PENALTY = get_detail (details, ly_symbol2scm ("collision-penalty"), 500);
- COLLISION_PADDING = get_detail (details, ly_symbol2scm ("collision-padding"), 0.5);
+
+ /* For grace notes, beams get scaled down to 80%, but glyphs go down
+ to 63% (magstep -4 for accidentals). To make the padding
+ commensurate with glyph size for grace notes, we take the square
+ of the length fraction, yielding a 64% decrease.
+ */
+ COLLISION_PADDING = get_detail (details, ly_symbol2scm ("collision-padding"), 0.5)
+ * sqr (robust_scm2double(him->get_property ("length-fraction"), 1.0));
STEM_COLLISION_FACTOR = get_detail (details, ly_symbol2scm ("stem-collision-factor"), 0.1);
}
the stems. Otherwise, we want to do initial slope calculations.
*/
do_initial_slope_calculations_ = false;
- Direction d = LEFT;
- do
+ for (LEFT_and_RIGHT (d))
do_initial_slope_calculations_ |= isinf (unquanted_y_[d]) || isnan (unquanted_y_[d]);
- while (flip (&d) != LEFT);
/*
Calculations are relative to a unit-scaled staff, i.e. the quants are
for (int a = 2; a--;)
common[a] = common_refpoint_of_array (stems, beams[i], Axis (a));
- Direction d = LEFT;
- do
+ for (LEFT_and_RIGHT (d))
common[X_AXIS] = beams[i]->get_bound (d)->common_refpoint (common[X_AXIS], X_AXIS);
- while (flip (&d) != LEFT);
// positions of the endpoints of this beam segment, including any overhangs
const Interval x_pos = robust_scm2interval (beams[i]->get_property ("X-positions"),
edge_dirs_ = Drul_array<Direction> (stem_infos_[0].dir_,
stem_infos_.back ().dir_);
- is_xstaff_ = Align_interface::has_interface (common[Y_AXIS]);
+ is_xstaff_ = has_interface<Align_interface> (common[Y_AXIS]);
is_knee_ |= dirs_found[DOWN] && dirs_found[UP];
staff_radius_ = Staff_symbol_referencer::staff_radius (beams[i]);
// TODO - why are we dividing by staff_space_?
beam_translation_ = Beam::get_beam_translation (beams[i]) / staff_space_;
- d = LEFT;
- do
+ for (LEFT_and_RIGHT (d))
{
quant_range_[d].set_full ();
if (!edge_stems[d])
+ (edge_beam_counts_[d] - 1) * beam_translation_ + beam_thickness_ * .5);
quant_range_[d][-ed] = heads[ed] + stem_offset;
}
- while (flip (&d) != LEFT);
segments_ = Beam::get_beam_segments (beams[i]);
vector_sort (segments_, beam_segment_less);
if (!collisions[j]->is_live ())
continue;
- if (Beam::has_interface (collisions[j]) && Beam::is_cross_staff (collisions[j]))
+ if (has_interface<Beam> (collisions[j]) && Beam::is_cross_staff (collisions[j]))
continue;
Box b;
Real width = b[X_AXIS].length ();
Real width_factor = sqrt (width / staff_space_);
- Direction d = LEFT;
- do
+ for (LEFT_and_RIGHT (d))
add_collision (b[X_AXIS][d], b[Y_AXIS], width_factor);
- while (flip (&d) != LEFT);
- Grob *stem = unsmob_grob (collisions[j]->get_object ("stem"));
- if (stem && Stem::has_interface (stem) && Stem::is_normal_stem (stem))
+ Grob *stem = unsmob<Grob> (collisions[j]->get_object ("stem"));
+ if (has_interface<Stem> (stem) && Stem::is_normal_stem (stem))
{
colliding_stems.insert (stem);
}
for (set<Grob *>::const_iterator it (colliding_stems.begin ()); it != colliding_stems.end (); it++)
{
Grob *s = *it;
- Real x = (s->extent (common[X_AXIS], X_AXIS) - x_pos[LEFT] + x_span_).center ();
+ Real x = (robust_relative_extent (s, common[X_AXIS], X_AXIS) - x_pos[LEFT] + x_span_).center ();
Direction stem_dir = get_grob_direction (*it);
Interval y;
- my_y;
Real factor = parameters_.STEM_COLLISION_FACTOR;
- if (!unsmob_grob (s->get_object ("beam")))
+ if (!unsmob<Grob> (s->get_object ("beam")))
factor = 1.0;
add_collision (x, y, factor);
}
if (scm_is_number (conc))
return scm_to_double (conc);
- if (is_knee_)
+ if (is_knee_ || is_xstaff_)
return 0.0;
Direction beam_dir = CENTER;
if (collisions_[i].y_.length () < min_y_size)
continue;
- Direction d = LEFT;
- do
+ for (LEFT_and_RIGHT (d))
{
Real dy = slope * collisions_[i].x_;
- Direction yd = DOWN;
Interval disallowed;
- do
+ for (DOWN_and_UP (yd))
{
Real left_y = collisions_[i].y_[yd] - dy;
disallowed[yd] = left_y;
}
- while (flip (&yd) != DOWN);
forbidden_intervals.push_back (disallowed);
}
- while (flip (&d) != LEFT);
}
vector_sort (forbidden_intervals, Interval::left_less);
// if the beam placement falls out of the feasible region, we push it
// to infinity so that it can never be a feasible candidate below
- Direction d = DOWN;
- do
+ for (DOWN_and_UP (d))
{
if (!feasible_left_point.contains (feasible_beam_placements[d]))
feasible_beam_placements[d] = d * infinity_f;
}
- while (flip (&d) != DOWN);
if ((feasible_beam_placements[UP] == infinity_f && feasible_beam_placements[DOWN] == -infinity_f) && !feasible_left_point.is_empty ())
{
Interval (unshifted_quants[i],
unshifted_quants[j]));
- Direction d = LEFT;
- do
+ for (LEFT_and_RIGHT (d))
{
if (!quant_range_[d].contains (c->y[d]))
{
break;
}
}
- while (flip (&d) != LEFT);
if (c)
scores->push_back (c);
}
}
/* Divide by number of stems, to make the measure scale-free. */
- Direction d = DOWN;
- do
+ for (DOWN_and_UP (d))
score[d] /= max (count[d], 1);
- while (flip (&d) != DOWN);
/*
sometimes, two perfectly symmetric kneed beams will have the same score
{
Real dy = config->y.delta ();
- Real extra_demerit = parameters_.SECONDARY_BEAM_DEMERIT
- / max (edge_beam_counts_[LEFT], edge_beam_counts_[RIGHT]);
-
- Direction d = LEFT;
+ Real extra_demerit =
+ parameters_.SECONDARY_BEAM_DEMERIT
+ / max (edge_beam_counts_[LEFT], edge_beam_counts_[RIGHT]);
+
Real dem = 0.0;
Real eps = parameters_.BEAM_EPS;
- do
+ for (LEFT_and_RIGHT (d))
{
for (int j = 1; j <= edge_beam_counts_[d]; j++)
{
Direction stem_dir = edge_dirs_[d];
/*
- The 2.2 factor is to provide a little leniency for
+ The fudge_factor is to provide a little leniency for
borderline cases. If we do 2.0, then the upper outer line
will be in the gap of the (2, sit) quant, leading to a
- false demerit.
+ false demerit. By increasing the fudge factor to 2.2, we
+ fix this case.
*/
- Real gap1 = config->y[d] - stem_dir * ((j - 1) * beam_translation_ + beam_thickness_ / 2 - line_thickness_ / 2.2);
- Real gap2 = config->y[d] - stem_dir * (j * beam_translation_ - beam_thickness_ / 2 + line_thickness_ / 2.2);
+ Real fudge_factor = 2.2;
+ Real gap1 = config->y[d] - stem_dir * ((j - 1) * beam_translation_ + beam_thickness_ / 2 - line_thickness_ / fudge_factor);
+ Real gap2 = config->y[d] - stem_dir * (j * beam_translation_ - beam_thickness_ / 2 + line_thickness_ / fudge_factor);
Interval gap;
gap.add_point (gap1);
}
}
}
- while ((flip (&d)) != LEFT);
+ config->add (dem, "Fl");
+ dem = 0.0;
if (max (edge_beam_counts_[LEFT], edge_beam_counts_[RIGHT]) >= 2)
{
Real straddle = 0.0;
Real inter = 0.5;
Real hang = 1.0 - (beam_thickness_ - line_thickness_) / 2;
- Direction d = LEFT;
- do
+ for (LEFT_and_RIGHT (d))
{
if (edge_beam_counts_[d] >= 2
&& fabs (config->y[d] - edge_dirs_[d] * beam_translation_) < staff_radius_ + inter)
dem += extra_demerit;
}
}
- while (flip (&d) != LEFT);
}
- config->add (dem, "F");
+ config->add (dem, "Fs");
}
void
Real dist = infinity_f;
if (!intersection (beam_y, collision_y).is_empty ())
dist = 0.0;
- else
+ else
dist = min (beam_y.distance (collision_y[DOWN]),
beam_y.distance (collision_y[UP]));
+
Real scale_free
= max (parameters_.COLLISION_PADDING - dist, 0.0)
/ parameters_.COLLISION_PADDING;
- demerits
- += collisions_[i].base_penalty_ *
+ Real collision_demerit = collisions_[i].base_penalty_ *
pow (scale_free, 3) * parameters_.COLLISION_PENALTY;
+
+ if (collision_demerit > 0) {
+ demerits += collision_demerit;
+ }
}
config->add (demerits, "C");