X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fslur-scoring.cc;h=63160a99171872556acb773a43bc046b773ebdce;hb=446103a87933b297c209e87fec94e97fe9462ad0;hp=6dc6b5718ac487d2a1c6256df93ea3f4420d39ac;hpb=87eedcd59f4082cb0841528ad5bc82cb1d1191e3;p=lilypond.git diff --git a/lily/slur-scoring.cc b/lily/slur-scoring.cc index 6dc6b5718a..63160a9917 100644 --- a/lily/slur-scoring.cc +++ b/lily/slur-scoring.cc @@ -1,15 +1,28 @@ /* - slur-scoring.cc -- Score based slur formatting + This file is part of LilyPond, the GNU music typesetter. - source file of the GNU LilyPond music typesetter - - (c) 1996--2007 Han-Wen Nienhuys + Copyright (C) 1996--2011 Han-Wen Nienhuys Jan Nieuwenhuizen + + LilyPond is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + LilyPond is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with LilyPond. If not, see . */ #include "slur-scoring.hh" +#include + #include "accidental-interface.hh" #include "beam.hh" #include "directional-element-interface.hh" @@ -67,18 +80,24 @@ Slur_score_state::~Slur_score_state () } /* - copy slur dir forwards across line break. + If a slur is broken across a line break, the direction + of the post-break slur must be the same as the pre-break + slur. */ -void -Slur_score_state::set_next_direction () +Direction +Slur_score_state::slur_direction () const { - if (extremes_[RIGHT].note_column_) - return; + Grob *left_neighbor = slur_->broken_neighbor (LEFT); - if (Grob *neighbor = slur_->broken_neighbor (RIGHT)) - { - set_grob_direction (neighbor, dir_); - } + if (left_neighbor && left_neighbor->is_live ()) + return get_grob_direction (left_neighbor); + + Direction dir = get_grob_direction (slur_); + + if (Grob *right_neighbor = slur_->broken_neighbor (RIGHT)) + set_grob_direction (right_neighbor, dir); + + return dir; } Encompass_info @@ -116,7 +135,7 @@ Slur_score_state::get_encompass_info (Grob *col) const { ei.stem_ = stem->extent (common_[Y_AXIS], Y_AXIS)[dir_]; if (Grob *b = Stem::get_beam (stem)) - ei.stem_ += stem_dir * 0.5 * Beam::get_thickness (b); + ei.stem_ += stem_dir * 0.5 * Beam::get_beam_thickness (b); Interval x = stem->extent (common_[X_AXIS], X_AXIS); ei.x_ = x.is_empty () @@ -204,7 +223,7 @@ Slur_score_state::fill (Grob *me) Real lt = me->layout ()->get_dimension (ly_symbol2scm ("line-thickness")); thickness_ = robust_scm2double (me->get_property ("thickness"), 1.0) * lt; - dir_ = get_grob_direction (me); + dir_ = slur_direction (); parameters_.fill (me); extract_grob_set (me, "note-columns", columns); @@ -266,14 +285,12 @@ Slur_score_state::fill (Grob *me) = (extremes_[LEFT].stem_ && Stem::get_beam (extremes_[LEFT].stem_)) || (extremes_[RIGHT].stem_ && Stem::get_beam (extremes_[RIGHT].stem_)); - set_next_direction (); - if (is_broken_) musical_dy_ = 0.0; } -MAKE_SCHEME_CALLBACK(Slur, calc_control_points, 1) +MAKE_SCHEME_CALLBACK (Slur, calc_control_points, 1) SCM Slur::calc_control_points (SCM smob) { @@ -288,17 +305,35 @@ Slur::calc_control_points (SCM smob) state.generate_curves (); SCM end_ys = me->get_property ("positions"); - Bezier best; + SCM inspect_quants = me->get_property ("inspect-quants"); + bool debug_slurs = to_boolean (me->layout () + ->lookup_variable (ly_symbol2scm ("debug-slur-scoring"))); + if (is_number_pair (inspect_quants)) + { + debug_slurs = true; + end_ys = inspect_quants; + } + + Slur_configuration *best = NULL; if (is_number_pair (end_ys)) - best = state.configurations_[state.get_closest_index (end_ys)]->curve_; + best = state.get_forced_configuration (ly_scm2interval(end_ys)); else best = state.get_best_curve (); +#if DEBUG_SLUR_SCORING + if (debug_slurs) + { + string total = best->card (); + total += to_string (" TOTAL=%.2f idx=%d", best->score (), best->index_); + me->set_property ("annotation", ly_string2scm (total)); + } +#endif + SCM controls = SCM_EOL; for (int i = 4; i--;) { - Offset o = best.control_[i] + Offset o = best->curve_.control_[i] - Offset (me->relative_coordinate (state.common_[X_AXIS], X_AXIS), me->relative_coordinate (state.common_[Y_AXIS], Y_AXIS)); controls = scm_cons (ly_offset2scm (o), controls); @@ -307,72 +342,52 @@ Slur::calc_control_points (SCM smob) return controls; } -Bezier -Slur_score_state::get_best_curve () +Slur_configuration* +Slur_score_state::get_forced_configuration (Interval ys) const { - int opt_idx = -1; - Real opt = 1e6; - -#if DEBUG_SLUR_SCORING - bool debug_slurs = to_boolean (slur_->layout () - ->lookup_variable (ly_symbol2scm ("debug-slur-scoring"))); - SCM inspect_quants = slur_->get_property ("inspect-quants"); - SCM inspect_index = slur_->get_property ("inspect-index"); - if (debug_slurs - && scm_is_integer (inspect_index)) - { - opt_idx = scm_to_int (inspect_index); - configurations_[opt_idx]->calculate_score (*this); - opt = configurations_[opt_idx]->score (); - } - else if (debug_slurs - && scm_is_pair (inspect_quants)) - { - opt_idx = get_closest_index (inspect_quants); - configurations_[opt_idx]->calculate_score (*this); - opt = configurations_[opt_idx]->score (); - } - else -#endif + Slur_configuration *best = NULL; + Real mindist = 1e6; + for (vsize i = 0; i < configurations_.size (); i++) { - for (vsize i = 0; i < configurations_.size (); i++) - configurations_[i]->calculate_score (*this); - for (vsize i = 0; i < configurations_.size (); i++) + Real d = fabs (configurations_[i]->attachment_[LEFT][Y_AXIS] - ys[LEFT]) + + fabs (configurations_[i]->attachment_[RIGHT][Y_AXIS] - ys[RIGHT]); + if (d < mindist) { - if (configurations_[i]->score () < opt) - { - opt = configurations_[i]->score (); - opt_idx = i; - } + best = configurations_[i]; + mindist = d; } } -#if DEBUG_SLUR_SCORING - if (debug_slurs) - { - string total; - if (opt_idx >= 0) - { - total = configurations_[opt_idx]->card (); - total += to_string (" TOTAL=%.2f idx=%d", configurations_[opt_idx]->score (), opt_idx); - } - else - { - total = "no sol?"; - } + while (!best->done ()) + best->run_next_scorer (*this); - slur_->set_property ("quant-score", - ly_string2scm (total)); - } -#endif + if (mindist > 1e5) + programming_error ("cannot find quant"); - if (opt_idx < 0) - { - opt_idx = 0; - programming_error ("No optimal slur found. Guessing 0."); - } - - return configurations_[opt_idx]->curve_; + return best; +} + + +Slur_configuration * +Slur_score_state::get_best_curve () const +{ + std::priority_queue, + Slur_configuration_less> queue; + for (vsize i = 0; i < configurations_.size (); i++) + queue.push (configurations_[i]); + + Slur_configuration *best = NULL; + while (true) { + best = queue.top (); + if (best->done ()) + break; + + queue.pop (); + best->run_next_scorer (*this); + queue.push (best); + } + + return best; } Grob * @@ -392,28 +407,6 @@ Slur_score_state::breakable_bound_item (Direction d) const return 0; } -int -Slur_score_state::get_closest_index (SCM inspect_quants) const -{ - Drul_array ins = ly_scm2interval (inspect_quants); - - int opt_idx = -1; - Real mindist = 1e6; - for (vsize i = 0; i < configurations_.size (); i++) - { - Real d = fabs (configurations_[i]->attachment_[LEFT][Y_AXIS] - ins[LEFT]) - + fabs (configurations_[i]->attachment_[RIGHT][Y_AXIS] - ins[RIGHT]); - if (d < mindist) - { - opt_idx = i; - mindist = d; - } - } - if (mindist > 1e5) - programming_error ("cannot find quant"); - return opt_idx; -} - /* TODO: should analyse encompasses to determine sensible region, and should limit slopes available. @@ -621,7 +614,7 @@ Slur_score_state::generate_avoid_offsets () const if (!xe.is_empty () && !ye.is_empty ()) - avoid.push_back (Offset (xe.center(), ye[dir_])); + avoid.push_back (Offset (xe.center (), ye[dir_])); } } return avoid; @@ -653,7 +646,6 @@ Slur_score_state::enumerate_attachments (Drul_array end_ys) const os[RIGHT] = base_attachments_[RIGHT]; for (int j = 0; dir_ * os[RIGHT][Y_AXIS] <= dir_ * end_ys[RIGHT]; j++) { - Slur_configuration s; Direction d = LEFT; Drul_array attach_to_stem (false, false); do @@ -714,10 +706,7 @@ Slur_score_state::enumerate_attachments (Drul_array end_ys) const } while (flip (&d) != LEFT); - s.attachment_ = os; - s.index_ = scores.size (); - - scores.push_back (new Slur_configuration (s)); + scores.push_back (Slur_configuration::new_config (os, scores.size ())); os[RIGHT][Y_AXIS] += dir_ * staff_space_ / 2; }