X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fslur-configuration.cc;h=a5d783703cbebdd43f7fd40aa6067680728c70f8;hb=0b544cfb7332615ef809b71b57ab656741311ae1;hp=c446ca1a12cbf59d9c9a1ef0d621253dfdf59dab;hpb=ac1f5ee6bc66e39e4fec27434ebb7c7300bab71e;p=lilypond.git diff --git a/lily/slur-configuration.cc b/lily/slur-configuration.cc index c446ca1a12..a5d783703c 100644 --- a/lily/slur-configuration.cc +++ b/lily/slur-configuration.cc @@ -1,7 +1,7 @@ /* This file is part of LilyPond, the GNU music typesetter. - Copyright (C) 2004--2012 Han-Wen Nienhuys + Copyright (C) 2004--2014 Han-Wen Nienhuys LilyPond is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -28,6 +28,7 @@ #include "spanner.hh" #include "staff-symbol-referencer.hh" #include "stem.hh" +#include "tie.hh" #include "warn.hh" Bezier @@ -42,27 +43,41 @@ avoid_staff_line (Slur_score_state const &state, && (state.extremes_[LEFT].staff_ == state.extremes_[RIGHT].staff_) && state.extremes_[LEFT].staff_ && state.extremes_[RIGHT].staff_) { - Real y = bez.curve_point (ts[0])[Y_AXIS]; + Real t = ts[0]; //the first (usually only) point where slur is horizontal + Real y = bez.curve_point (t)[Y_AXIS]; + // A Bezier curve at t moves 3t-3t² as far as the middle control points + Real factor = 3.0 * t * (1.0 - t); Grob *staff = state.extremes_[LEFT].staff_; Real p = 2 * (y - staff->relative_coordinate (state.common_[Y_AXIS], Y_AXIS)) / state.staff_space_; - Real const round = my_round (p); - Real const frac = p - round; - if (fabs (frac) < 4 * state.thickness_ - && Staff_symbol_referencer::on_staff_line (staff, int (round))) + int round_p = (int) my_round (p); + if (!Staff_symbol_referencer::on_staff_line (staff, round_p)) + round_p += (p > round_p) ? 1 : -1; + if (!Staff_symbol_referencer::on_staff_line (staff, round_p)) + return bez; + + Real const distance = (p - round_p) * state.staff_space_ / 2.0; + // Allow half the thickness of the slur at the point t, plus one basic + // blot-diameter (half for the slur outline, half for the staff line) + Real const min_distance = 0.5 * state.thickness_ * factor + + state.line_thickness_ + + ((state.dir_ * distance > 0.0) + ? state.parameters_.gap_to_staffline_inside_ + : state.parameters_.gap_to_staffline_outside_); + if (fabs (distance) < min_distance) { - Direction resolution_dir = frac ? state.dir_ : CENTER; + Direction resolution_dir = (distance > 0.0) ? UP : DOWN; - // TODO: parameter - Real newp = round + resolution_dir * 5 * state.thickness_; - - Real dy = (newp - p) * state.staff_space_ / 2.0; + Real dy = resolution_dir * (min_distance - fabs (distance)); + // Shape the curve, moving the horizontal point by factor * dy bez.control_[1][Y_AXIS] += dy; bez.control_[2][Y_AXIS] += dy; + // Move the entire curve by the remaining amount + bez.translate (Offset (0.0, dy - factor * dy)); } } return bez; @@ -186,11 +201,11 @@ Slur_configuration::Slur_configuration () }; void -Slur_configuration::add_score (Real s, string desc) +Slur_configuration::add_score (Real s, const string &desc) { if (s < 0) { - programming_error ("Negative demerits found for slur. Ignoring"); + programming_error ("Negative demerits found for slur. Ignoring"); s = 0.0; } @@ -316,6 +331,39 @@ Slur_configuration::score_encompass (Slur_score_state const &state) void Slur_configuration::score_extra_encompass (Slur_score_state const &state) { + // we find forbidden attachments + vector forbidden_attachments; + for (vsize i = 0; i < state.extra_encompass_infos_.size (); i++) + if (Tie::has_interface (state.extra_encompass_infos_[i].grob_)) + { + Grob *t = state.extra_encompass_infos_[i].grob_; + Grob *common_x = Grob::get_vertical_axis_group (t); + Real rp = t->relative_coordinate (common_x, X_AXIS); + SCM cp = t->get_property ("control-points"); + + Bezier b; + int j = 0; + for (SCM s = cp; scm_is_pair (s); s = scm_cdr (s)) + { + b.control_[j] = ly_scm2offset (scm_car (s)); + j++; + } + forbidden_attachments.push_back (Offset (b.control_[0]) + Offset (rp, 0)); + forbidden_attachments.push_back (Offset (b.control_[3]) + Offset (rp, 0)); + } + + bool too_close = false; + for (vsize k = 0; k < forbidden_attachments.size (); k++) + for (LEFT_and_RIGHT (side)) + if ((forbidden_attachments[k] - attachment_[side]).length () < state.parameters_.slur_tie_extrema_min_distance_) + { + too_close = true; + break; + } + + if (too_close) + add_score (state.parameters_.slur_tie_extrema_min_distance_penalty_, "extra"); + for (vsize j = 0; j < state.extra_encompass_infos_.size (); j++) { Drul_array attachment = attachment_;