X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fnew-slur.cc;h=62f9400398c4a3738e8f241571685272206193d2;hb=f2731e17f7fca531ef4c4d0a2d7299592015745a;hp=92bfe9946764f8ad953067bc92e1e80c587f6b54;hpb=e3de11d24da9da9f7bf3f0f5a879ae5c105708ae;p=lilypond.git diff --git a/lily/new-slur.cc b/lily/new-slur.cc index 92bfe99467..62f9400398 100644 --- a/lily/new-slur.cc +++ b/lily/new-slur.cc @@ -4,12 +4,13 @@ source file of the GNU LilyPond music typesetter (c) 1996--2004 Han-Wen Nienhuys - Jan Nieuwenhuizen + Jan Nieuwenhuizen */ #include +#include "main.hh" #include "font-interface.hh" #include "text-item.hh" #include "directional-element-interface.hh" @@ -27,6 +28,7 @@ #include "stem.hh" #include "stencil.hh" #include "warn.hh" +#include "beam.hh" /* TODO: @@ -35,8 +37,7 @@ - curve around flag/stem for x coordinate - better scoring. - */ - +*/ struct Encompass_info { Real x_; Real stem_; @@ -49,19 +50,69 @@ struct Encompass_info { } }; +struct Bound_info { + + Box stem_extent_; + Direction stem_dir_; + Grob *bound_; + Grob *note_column_; + Grob *slur_head_; + Grob *staff_; + Grob *stem_; + Interval slur_head_extent_; + Real neighbor_y_; + + Bound_info () { + stem_ = 0; + neighbor_y_ = 0; + staff_ = 0; + slur_head_ = 0; + stem_dir_ = CENTER; + note_column_ = 0; + } +}; + /* - TODO: put in details list. - */ -const int SLUR_REGION_SIZE = 5; -const Real HEAD_ENCOMPASS_PENALTY = 1000.0; -const Real STEM_ENCOMPASS_PENALTY = 30.0; -const Real CLOSENESS_FACTOR = 10; -const Real EDGE_ATTRACTION_FACTOR = 4; -const Real HEAD_FREE_SPACE = 0.3; -const Real SAME_SLOPE_PENALTY = 20; -const Real STEEPER_SLOPE_FACTOR = 50; -const Real NON_HORIZONTAL_PENALTY = 15; -const Real HEAD_STRICT_FREE_SPACE = 0.2; + TODO: put in details property. +*/ +struct Slur_score_parameters +{ + int SLUR_REGION_SIZE ; + Real HEAD_ENCOMPASS_PENALTY ; + Real STEM_ENCOMPASS_PENALTY ; + Real CLOSENESS_FACTOR ; + Real EDGE_ATTRACTION_FACTOR ; + Real SAME_SLOPE_PENALTY ; + Real STEEPER_SLOPE_FACTOR ; + Real NON_HORIZONTAL_PENALTY ; + Real HEAD_STRICT_FREE_SPACE ; + Real MAX_SLOPE ; + Real MAX_SLOPE_FACTOR ; + Real FREE_HEAD_DISTANCE ; + Slur_score_parameters (); +}; + +void +init_score_param (Slur_score_parameters *score_param) +{ + score_param->SLUR_REGION_SIZE = 5; + score_param->HEAD_ENCOMPASS_PENALTY = 1000.0; + score_param->STEM_ENCOMPASS_PENALTY = 30.0; + score_param->CLOSENESS_FACTOR = 10; + score_param->EDGE_ATTRACTION_FACTOR = 4; + score_param->SAME_SLOPE_PENALTY = 20; + score_param->STEEPER_SLOPE_FACTOR = 50; + score_param->NON_HORIZONTAL_PENALTY = 15; + score_param->HEAD_STRICT_FREE_SPACE = 0.2; + score_param->MAX_SLOPE = 1.1; + score_param->MAX_SLOPE_FACTOR = 10; + score_param->FREE_HEAD_DISTANCE = 0.3 ; +} + +Slur_score_parameters::Slur_score_parameters() +{ + init_score_param (this); +} #define DEBUG_SLUR_QUANTING 1 @@ -84,31 +135,113 @@ class New_slur public: static void add_column (Grob *me, Grob *col); DECLARE_SCHEME_CALLBACK (print, (SCM)); - static void score_slopes (Grob * me, Grob *common[], Drul_array base_attach, + static void score_slopes (Grob * me, Grob *common[], + Slur_score_parameters * score_param, + + Drul_array, + Drul_array base_attach, Array * scores); - static void score_encompass (Grob * me, Grob *common[], - Drul_array, Array * scores); + static void score_edges (Grob * me, Grob *common[], + Slur_score_parameters * score_param, + + Drul_array extremes, + Drul_array base_attach, + Array * scores); + static void score_encompass (Grob * me, Grob *common[], + Slur_score_parameters*, + Drul_array, + Drul_array, Array * scores); + + static Encompass_info get_encompass_info (Grob *me, + Grob *col, + Grob **common) ; static void set_interface (Grob*); static bool has_interface (Grob*); - static Array get_encompass_offsets (Grob *me); static Bezier get_curve (Grob *me); static Bezier get_bezier (Grob *me, Drul_array,Real,Real); static Direction get_default_dir (Grob *me); DECLARE_SCHEME_CALLBACK (after_line_breaking, (SCM)); DECLARE_SCHEME_CALLBACK (height, (SCM,SCM)); -private: + static void set_end_points (Grob*); static Real get_boundary_notecolumn_y (Grob *me, Direction dir); - static Offset broken_trend_offset (Grob *me, Direction dir); - static Offset get_attachment (Grob *me,Direction dir, Grob **common); - static void de_uglyfy (Grob *me,Slur_bezier_bow* bb, Real default_height); - static SCM set_extremities (Grob *me); + static Real broken_trend_y (Grob *me, Grob**, Direction dir); static void set_control_points (Grob *me); - static void check_slope (Grob *me); - static Encompass_info get_encompass_info (Grob *me, Grob *col, Grob **common); + static Drul_array get_bound_info (Spanner* me, + Grob **common); + + static void generate_curves (Grob*me, Array *scores); + static Array enumerate_attachments (Grob * me, Grob *common[], + Slur_score_parameters * score_param, + Drul_array extremes, + Drul_array base_attachment, Drul_array end_ys); + ; + static Drul_array get_base_attachments (Spanner*sp, + Grob **common, + + Drul_array extremes); + + static Drul_array get_y_attachment_range (Spanner*sp, + Grob **common, + + Drul_array extremes, + Drul_array base_attachment); }; +Real +New_slur::broken_trend_y (Grob *me, Grob**common, Direction hdir) +{ + /* + A broken slur should maintain the same vertical trend + the unbroken slur would have had. + */ + Real by = 0.0; + if (Spanner *mother = dynamic_cast (me->original_)) + { + int k = broken_spanner_index (dynamic_cast (me)); + int j = k + hdir; + if (j < 0 || j >= mother->broken_intos_.size ()) + return by; + + Grob *neighbor = mother->broken_intos_[j]; + if (hdir == RIGHT) + neighbor->set_property ("direction", + me->get_property ("direction")); + + Spanner * common_mother = dynamic_cast (common[Y_AXIS]->original_); + int common_k = broken_spanner_index (dynamic_cast (common[Y_AXIS])); + int common_j = common_k + hdir; + + if (common_j < 0 || common_j >= common_mother->broken_intos_.size()) + return by; + + + Grob *common_next_system = common_mother->broken_intos_[common_j]; + Link_array neighbor_cols = + Pointer_group_interface__extract_grobs (neighbor, (Grob*)0, "note-columns"); + + Grob * neighbor_col = (hdir == RIGHT) ? neighbor_cols[0] : neighbor_cols.top (); + Grob * neighbor_common = common_next_system->common_refpoint (neighbor_col, Y_AXIS); + + Direction vdir = get_grob_direction (me); + Real neighbor_y = + neighbor_col->extent (neighbor_common, Y_AXIS) + .linear_combination (int(neighbor_cols.size()==1 ? CENTER : vdir)) + - common_next_system->relative_coordinate (neighbor_common, Y_AXIS); + + Link_array my_cols = + Pointer_group_interface__extract_grobs (me, (Grob*)0, "note-columns"); + + Grob *extreme_col = (hdir == RIGHT) ? my_cols.top() : my_cols[0]; + Real y = extreme_col->extent (common[Y_AXIS], Y_AXIS).linear_combination (vdir); + + by = (y*neighbor_cols.size() + neighbor_y*my_cols.size()) / + (my_cols.size() + neighbor_cols.size()); + } + return by; +} + void New_slur::set_interface (Grob*me) { @@ -128,8 +261,8 @@ New_slur::add_column (Grob*me, Grob*n) Encompass_info New_slur::get_encompass_info (Grob *me, - Grob *col, - Grob **common) + Grob *col, + Grob **common) { Grob* stem = unsmob_grob (col->get_property ("stem")); @@ -141,7 +274,7 @@ New_slur::get_encompass_info (Grob *me, { programming_error ("No stem for note column?"); ei.x_ = col->relative_coordinate (common[X_AXIS], X_AXIS); - ei.head_ = ei.stem_ = col->relative_coordinate (common[Y_AXIS], Y_AXIS); + ei.head_ = ei.stem_ = col->extent (common[Y_AXIS], Y_AXIS)[get_grob_direction (me)]; return ei; } Direction stem_dir = get_grob_direction (stem); @@ -154,7 +287,7 @@ New_slur::get_encompass_info (Grob *me, Grob * h = Stem::extremal_heads (stem)[Direction (dir)]; if (!h) { - ei.head_ = ei.stem_ = col->relative_coordinate (common[Y_AXIS], Y_AXIS); + ei.head_ = ei.stem_ = col->extent (common[Y_AXIS], Y_AXIS)[dir]; return ei; } @@ -164,6 +297,11 @@ New_slur::get_encompass_info (Grob *me, && !stem->extent (stem, Y_AXIS).is_empty ()) { 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); + } + } else ei.stem_ = ei.head_; @@ -205,10 +343,6 @@ New_slur::after_line_breaking (SCM smob) set_grob_direction (me, get_default_dir (me)); - if (!Note_column::has_interface (me->get_bound (LEFT)) - || !Note_column::has_interface (me->get_bound (RIGHT))) - me->suicide (); // fixme. - set_end_points (me); return SCM_UNSPECIFIED; @@ -229,22 +363,51 @@ New_slur::get_bezier (Grob *me, Drul_array extremes, return bb.get_bezier (); } + +Drul_array +New_slur::get_bound_info (Spanner* me, + Grob **common) +{ + Drul_array extremes; + Direction d = LEFT; + Direction dir = get_grob_direction (me); + + do { + extremes[d].bound_ = me->get_bound (d); + + if (Note_column::has_interface (extremes[d].bound_)) + { + extremes[d].note_column_ = extremes[d].bound_; + extremes[d].stem_ = Note_column::get_stem (extremes[d].note_column_); + extremes[d].stem_dir_ = get_grob_direction (extremes[d].stem_); + extremes[d].stem_extent_[X_AXIS] = extremes[d].stem_->extent (common[X_AXIS], X_AXIS); + extremes[d].stem_extent_[Y_AXIS] = extremes[d].stem_->extent (common[Y_AXIS], Y_AXIS); + extremes[d].slur_head_ = Stem::extremal_heads (extremes[d].stem_)[dir]; + extremes[d].slur_head_extent_ = extremes[d].slur_head_->extent (common[X_AXIS], X_AXIS); + extremes[d].staff_ = Staff_symbol_referencer::get_staff_symbol (extremes[d].slur_head_); + } + else + { + extremes[d].neighbor_y_ = broken_trend_y (me, common, d); + } + } while (flip (&d) != LEFT); + + return extremes; +} + void New_slur::set_end_points (Grob *me) { Link_array columns = Pointer_group_interface__extract_grobs (me, (Grob*)0, "note-columns"); + + Slur_score_parameters params; if (columns.is_empty ()) { me->suicide (); return ; } - Real staff_space = Staff_symbol_referencer::staff_space ((Grob*)me); - Drul_array extremes (columns[0], columns.top ()); - Direction dir = get_grob_direction (me); - - Drul_array base_attachment; SCM eltlist = me->get_property ("note-columns"); Grob *common[] = {common_refpoint_of_list (eltlist, me, X_AXIS), @@ -255,156 +418,264 @@ New_slur::set_end_points (Grob *me) common[X_AXIS] = common[X_AXIS]->common_refpoint (sp->get_bound (RIGHT), X_AXIS); common[X_AXIS] = common[X_AXIS]->common_refpoint (sp->get_bound (LEFT), X_AXIS); - Direction d = LEFT; - Drul_array staves; - - do { - Grob *stem = Note_column::get_stem (extremes[d]); - Grob * h = Stem::extremal_heads (stem)[Direction (dir)]; - staves[d] = Staff_symbol_referencer::get_staff_symbol (h); - common[Y_AXIS] = common[Y_AXIS]->common_refpoint (staves[d], Y_AXIS); - } while (flip (&d) != LEFT); - - do + Drul_array extremes = get_bound_info (sp, common); + Drul_array base_attachment = get_base_attachments (sp, common, extremes); + Drul_array end_ys = get_y_attachment_range (sp, common, extremes, base_attachment); + Array scores = enumerate_attachments (me, common, + ¶ms, extremes, base_attachment, end_ys); + generate_curves (me, &scores); + + score_edges (me, common, ¶ms,extremes, base_attachment, &scores); + score_slopes (me, common, ¶ms,extremes, base_attachment, &scores); + score_encompass (me, common, ¶ms,extremes, base_attachment, &scores); + + Real opt = 1e6; + int opt_idx = 0; + for (int i = scores.size (); i--;) { - // c&p - Grob *stem = Note_column::get_stem (extremes[d]); - Grob * h = Stem::extremal_heads (stem)[dir]; - - Real y; - - if (stem - && get_grob_direction (stem) == dir - && Stem::get_beam (stem)) + if (scores[i].score_ < opt) { - y = stem->extent (common[Y_AXIS], Y_AXIS)[dir]; + opt = scores[i].score_; + opt_idx = i; } - else + } + +#if DEBUG_SLUR_QUANTING + SCM inspect_quants = me->get_property ("inspect-quants"); + if (to_boolean (me->get_paper ()->lookup_variable (ly_symbol2scm ("debug-slur-quanting"))) + && ly_c_pair_p (inspect_quants)) + { + Drul_array ins = ly_scm2interval (inspect_quants); + int i = 0; + + Real mindist = 1e6; + for (; i < scores.size (); i ++) { - y = h->extent (common[Y_AXIS], Y_AXIS)[dir]; + Real d =fabs (scores[i].attachment_[LEFT][Y_AXIS] - ins[LEFT]) + + fabs (scores[i].attachment_[RIGHT][Y_AXIS] - ins[RIGHT]); + if (d < mindist) + { + opt_idx = i; + mindist= d; + } } + if (mindist > 1e5) + programming_error ("Could not find quant."); + } + + + scores[opt_idx].score_card_ += to_string ("i%d", opt_idx); + + // debug quanting + me->set_property ("quant-score", + scm_makfrom0str (scores[opt_idx].score_card_.to_str0 ())); +#endif + + Bezier const &b = scores[opt_idx].curve_; + + SCM controls = SCM_EOL; + for (int i = 4; i--;) + { + Offset o = b.control_[i] - + Offset (me->relative_coordinate (common[X_AXIS], X_AXIS), + me->relative_coordinate (common[Y_AXIS], Y_AXIS)); + + controls = scm_cons (ly_offset2scm (o), controls); + } - y += dir * 0.5 * staff_space; + me->set_property ("control-points", controls); +} - Grob * staff = Staff_symbol_referencer::get_staff_symbol (h); - Real pos = 2.0 * (y - staff->relative_coordinate (common[Y_AXIS], Y_AXIS)) / Staff_symbol::staff_space (staff); - - /* - start off staffline. - */ - if (fabs (pos - round (pos)) < 0.2 - && Staff_symbol_referencer::on_staffline (h, (int) rint (pos))) - y += staff_space * dir / 10 ; +Drul_array +New_slur::get_y_attachment_range (Spanner*me, + Grob **common, + Drul_array extremes, + Drul_array base_attachment) +{ + Drul_array end_ys; + Direction dir = get_grob_direction (me); + Direction d = LEFT; + do { + if (extremes[d].note_column_) + { + end_ys[d] = dir * ((dir * (base_attachment[d][Y_AXIS] + 4.0 *dir)) + >? (dir * (dir + extremes[d].note_column_->extent(common[Y_AXIS],Y_AXIS)[dir])) + >? (dir * base_attachment[-d][Y_AXIS]) + ); + } + else + { + end_ys[d] = extremes[d].neighbor_y_ + 4.0 * dir ; + } + } while (flip (&d) != LEFT); - - - Grob * fh = Note_column::first_head (extremes[d]); - Real x = fh->extent (common[X_AXIS], X_AXIS).linear_combination (CENTER); + return end_ys; +} - if (get_grob_direction (stem) == dir - && dir == -d) +Drul_array +New_slur::get_base_attachments (Spanner*me, + Grob **common, + Drul_array extremes) +{ + Link_array columns = + Pointer_group_interface__extract_grobs (me, (Grob*)0, "note-columns"); + Drul_array base_attachment; + + + Slur_score_parameters params; + + Real staff_space = Staff_symbol_referencer::staff_space ((Grob*)me); + + Direction dir = get_grob_direction (me); + Direction d = LEFT; + do + { + Grob *stem = extremes[d].stem_; + Grob *head = extremes[d].slur_head_; + + Real x,y; + if (!extremes[d].note_column_) { - x -= d * fh->extent(fh, X_AXIS).length (); + y = extremes[d].neighbor_y_; + if (d== RIGHT) + x = extremes[d].bound_->extent (common[X_AXIS], X_AXIS)[d]; + else + x = me->get_broken_left_end_align (); + } + else + { + if (stem + && extremes[d].stem_dir_ == dir + && Stem::get_beaming (stem, -d) + && columns.size () > 2 + ) + { + y = extremes[d].stem_extent_[Y_AXIS][dir]; + } + else if (head) + { + y = head->extent (common[Y_AXIS], Y_AXIS)[dir]; + } + y += dir * 0.5 * staff_space; + + Real pos = 2.0 * (y - extremes[d].staff_->relative_coordinate (common[Y_AXIS], Y_AXIS)) + / Staff_symbol::staff_space (extremes[d].staff_); + + /* + start off staffline. + */ + if (fabs (pos - round (pos)) < 0.2 + && Staff_symbol_referencer::on_staffline (head, (int) rint (pos)) + && Staff_symbol_referencer::line_count (head) -1 >= rint (pos) + ) + y += staff_space * dir / 10 ; + + Grob * fh = Note_column::first_head (extremes[d].note_column_); + x = fh->extent (common[X_AXIS], X_AXIS).linear_combination (CENTER); } - base_attachment[d] = Offset (x, y); } while (flip (&d) != LEFT); - Drul_array staff_offsets; - Interval end_ys; + return base_attachment; +} - do { - staff_offsets[d] = staves[d]->relative_coordinate (common[Y_AXIS], Y_AXIS); - end_ys[d] = dir * ((dir * (base_attachment[d][Y_AXIS] + 4.0 *dir)) >? - (dir * (dir + extremes[d]->extent(common[Y_AXIS],Y_AXIS)[dir]))); - } while (flip (&d) != LEFT); - + + +void +New_slur::generate_curves (Grob*me, Array *scores) + +{ + + Real staff_space = Staff_symbol_referencer::staff_space ((Grob*)me); + + Real r_0 = robust_scm2double (me->get_property ("ratio"), 1); + Real h_inf = staff_space * ly_scm2double (me->get_property ("height-limit")); + for (int i = scores->size(); i-- ;) + { + (*scores)[i].curve_ = get_bezier (me, (*scores)[i].attachment_, + r_0, h_inf); + } +} + +Array +New_slur::enumerate_attachments (Grob * me, Grob *common[], + Slur_score_parameters * score_param, + Drul_array extremes, + Drul_array base_attachment, + Drul_array end_ys) +{ + /*ugh. */ Array scores; + + Direction dir = get_grob_direction (me); + Real staff_space = Staff_symbol_referencer::staff_space ((Grob*)me); Drul_array os; - - /*ugh. */ os[LEFT] = base_attachment[LEFT]; - - for (int i = 0; dir * os[LEFT][Y_AXIS] < dir * end_ys[LEFT]; i++) + Real minimum_length = staff_space * robust_scm2double (me->get_property ("minimum-length"), + 2.0); + + for (int i = 0; dir * os[LEFT][Y_AXIS] <= dir * end_ys[LEFT]; i++) { os[RIGHT] = base_attachment[RIGHT]; - for (int j = 0; dir *os[RIGHT][Y_AXIS] < dir * end_ys[RIGHT]; j++) + for (int j = 0; dir *os[RIGHT][Y_AXIS] <= dir * end_ys[RIGHT]; j++) { Slur_score s; - s.attachment_ = os; + Direction d = LEFT; + + do { + os[d][X_AXIS] = base_attachment[d][X_AXIS]; + if (extremes[d].stem_ + && !Stem::is_invisible (extremes[d].stem_) + && extremes[d].stem_dir_ == dir + && dir == -d) + { + if (extremes[d].stem_extent_[Y_AXIS].contains (os[d][Y_AXIS])) + { + os[d][X_AXIS] = extremes[d].slur_head_extent_[-d] + - d * 0.3; + } + else if (dir *extremes[d].stem_extent_[Y_AXIS][dir] < dir * os[d][Y_AXIS]) + { + os[d][X_AXIS] = extremes[d].stem_extent_[X_AXIS].center(); + } + } + } while (flip (&d) != LEFT); + + Offset dz = os[RIGHT] - os[LEFT]; + if (dz[X_AXIS] < minimum_length + || fabs (dz[Y_AXIS] / dz[X_AXIS]) > score_param->MAX_SLOPE + ) + { + do { + if (extremes[d].slur_head_) + os[d][X_AXIS] = extremes[d].slur_head_extent_.center (); + } while (flip (&d) != LEFT); + } + + s.attachment_ = os; scores.push (s); - - Real incr = dir * staff_space; - if (Staff_symbol_referencer::staff_radius (staves[RIGHT]) - < fabs ((os[RIGHT][Y_AXIS] - staff_offsets[RIGHT]) / staff_space)) - incr /= 2; - - os[RIGHT][Y_AXIS] += incr; + + os[RIGHT][Y_AXIS] += dir * staff_space / 2; } - Real incr = dir * staff_space; - if (Staff_symbol_referencer::staff_radius (staves[LEFT]) - < fabs ((os[LEFT][Y_AXIS] - staff_offsets[LEFT]) / staff_space)) - incr /= 2; - - os[LEFT][Y_AXIS] += incr; - } - - { - Real r_0 = robust_scm2double (me->get_property ("ratio"), 1); - Real h_inf = staff_space * ly_scm2double (me->get_property ("height-limit")); - for (int i = scores.size(); i-- ;) - { - scores[i].curve_ = get_bezier (me, scores[i].attachment_, - r_0, h_inf); - } - } - - score_encompass (me, common, base_attachment, &scores); - score_slopes (me, common, base_attachment, &scores); - - Real opt = 1e6; - int opt_idx = 0; - for (int i = scores.size (); i--;) - { - if (scores[i].score_ < opt) - { - opt = scores[i].score_; - opt_idx = i; - } - } - - Bezier const &b = scores[opt_idx].curve_; - - SCM controls = SCM_EOL; - for (int i = 4; i--;) - { - Offset o = b.control_[i] - - Offset (me->relative_coordinate (common[X_AXIS], X_AXIS), - me->relative_coordinate (common[Y_AXIS], Y_AXIS)); - - controls = scm_cons (ly_offset2scm (o), controls); + os[LEFT][Y_AXIS] += dir * staff_space /2 ; } - me->set_property ("control-points", controls); - -#if DEBUG_SLUR_QUANTING - scores[opt_idx].score_card_ += to_string ("i%d", opt_idx); - - // debug quanting - me->set_property ("quant-score", - scm_makfrom0str (scores[opt_idx].score_card_.to_str0 ())); -#endif - + return scores; } + void -New_slur::score_encompass (Grob * me, Grob *common[], Drul_array base_attach, +New_slur::score_encompass (Grob * me, Grob *common[], + Slur_score_parameters * score_param, + + Drul_array extremes, + Drul_array base_attach, Array * scores) { Link_array encompasses = @@ -413,12 +684,9 @@ New_slur::score_encompass (Grob * me, Grob *common[], Drul_array base_a Array infos; - int first = 1; - int last = encompasses.size () - 2; - - for (int i = first; i <= last; i++) + for (int i = 0; i < encompasses.size(); i++) infos.push (get_encompass_info (me, encompasses[i], common)); - + for (int i =0 ; i < scores->size (); i++) { Bezier const &bez (scores->elem (i).curve_); @@ -428,36 +696,43 @@ New_slur::score_encompass (Grob * me, Grob *common[], Drul_array base_a Real x = infos[j].x_; if (!(x < scores->elem (i).attachment_[RIGHT][X_AXIS] - &&x > scores->elem (i).attachment_[LEFT][X_AXIS])) + && x > scores->elem (i).attachment_[LEFT][X_AXIS])) continue; Real y = bez.get_other_coordinate (X_AXIS, x); - if (dir * (y - infos[j].head_) < 0) - demerit += HEAD_ENCOMPASS_PENALTY; - + if (j && j < infos.size () -1) + { + Real head_dy = (y - infos[j].head_); + if (dir * head_dy < 0) + { + demerit += score_param->HEAD_ENCOMPASS_PENALTY; + } + else + { + Real hd = + (head_dy) ? (1/fabs (head_dy) - 1/score_param->FREE_HEAD_DISTANCE) + : score_param->HEAD_ENCOMPASS_PENALTY; + hd = (hd >? 0)HEAD_ENCOMPASS_PENALTY; + + demerit += hd; + } + } if (dir * (y - infos[j].stem_) < 0) - demerit += STEM_ENCOMPASS_PENALTY; - else + demerit += score_param->STEM_ENCOMPASS_PENALTY; + else if (j && j < encompasses.size () - 1) { Interval ext; ext.add_point (infos[j].stem_); ext.add_point (infos[j].head_); - demerit += - CLOSENESS_FACTOR * (dir * (y - (ext[dir] + dir * HEAD_FREE_SPACE)) CLOSENESS_FACTOR * (dir * (y - (ext[dir] + dir * score_param->FREE_HEAD_DISTANCE)) elem (i).attachment_[d][Y_AXIS] - base_attach[d][Y_AXIS]); - } while (flip (&d) != LEFT); - #if DEBUG_SLUR_QUANTING - (*scores)[i].score_card_ += to_string ("E%.2f", demerit); + (*scores)[i].score_card_ += to_string ("C%.2f", demerit); #endif (*scores)[i].score_ += demerit; @@ -466,52 +741,94 @@ New_slur::score_encompass (Grob * me, Grob *common[], Drul_array base_a void -New_slur::score_slopes (Grob * me, Grob *common[], Drul_array base_attach, - Array * scores) +New_slur::score_edges (Grob * me, Grob *common[], + Slur_score_parameters * score_param, + + Drul_array extremes, + Drul_array base_attach, + Array * scores) { - Link_array columns = - Pointer_group_interface__extract_grobs (me, (Grob*)0, "note-columns"); + Direction dir = get_grob_direction (me); + + for (int i =0 ; i < scores->size (); i++) + { + + Direction d = LEFT; + do { + Real y = scores->elem (i).attachment_[d][Y_AXIS]; + Real dy = fabs (y - base_attach[d][Y_AXIS]); + + Real factor = score_param->EDGE_ATTRACTION_FACTOR; + + Real demerit = + score_param->EDGE_ATTRACTION_FACTOR + * fabs (scores->elem (i).attachment_[d][Y_AXIS] - base_attach[d][Y_AXIS]); + + if (extremes[d].stem_ + && extremes[d].stem_dir_ == dir + && !Stem::get_beaming (extremes[d].stem_, -d) + ) + demerit /= 5; + + (*scores)[i].score_ += demerit; +#if DEBUG_SLUR_QUANTING + (*scores)[i].score_card_ += to_string ("E%.2f", demerit); +#endif + } while (flip (&d) != LEFT); + } +} - Drul_array extremes (columns[0], columns.top ()); +void +New_slur::score_slopes (Grob * me, Grob *common[], + Slur_score_parameters*score_param, + Drul_array extremes, + Drul_array base_attach, + Array * scores) +{ Direction dir = get_grob_direction (me); Drul_array ys; Direction d = LEFT; - Drul_array stem_dirs; - Drul_array beams; do { - Grob *stem = Note_column::get_stem (extremes [d]); - ys[d] = Stem::extremal_heads (stem)[Direction (dir)] - ->relative_coordinate (common[Y_AXIS], Y_AXIS); - stem_dirs[d] = get_grob_direction (stem); - beams[d] = Stem::get_beam (stem); + if (extremes[d].slur_head_) + ys[d] = extremes[d].slur_head_ ->relative_coordinate (common[Y_AXIS], Y_AXIS); + else + ys[d] = extremes[d].neighbor_y_; } while (flip (&d) != LEFT); + bool has_beams = + (extremes[LEFT].stem_ && Stem::get_beam (extremes[LEFT].stem_)) + || (extremes[RIGHT].stem_ && Stem::get_beam (extremes[RIGHT].stem_)); Real dy = ys[RIGHT] - ys[LEFT]; for (int i =0 ; i < scores->size (); i++) { - Real slur_dy = (*scores)[i].attachment_[RIGHT][Y_AXIS] - - (*scores)[i].attachment_[LEFT][Y_AXIS]; + Offset slur_dz = (*scores)[i].attachment_[RIGHT] + - (*scores)[i].attachment_[LEFT]; + + Real slur_dy = slur_dz[Y_AXIS]; + Real demerit = 0.0; + if (!has_beams) + /* + 0.2: account for staffline offset. + */ + demerit += score_param->STEEPER_SLOPE_FACTOR * (dir * (fabs (slur_dy) - fabs (dy + 0.2)) >? 0); - if(! (beams[LEFT] || beams[RIGHT])) - demerit += STEEPER_SLOPE_FACTOR * (dir * (fabs (slur_dy) - fabs (dy)) >? 0); + demerit += ((fabs (slur_dy/slur_dz[X_AXIS]) - score_param->MAX_SLOPE)>?0) * score_param->MAX_SLOPE_FACTOR; + if (sign (dy) == 0 && sign (slur_dy) != 0) - demerit += NON_HORIZONTAL_PENALTY; - - + demerit += score_param->NON_HORIZONTAL_PENALTY; if (sign (dy) && sign (slur_dy) && sign (slur_dy) != sign (dy)) demerit += - (beams[LEFT] || beams[RIGHT]) - ? SAME_SLOPE_PENALTY/10 : SAME_SLOPE_PENALTY; + has_beams ? score_param->SAME_SLOPE_PENALTY/10 : score_param->SAME_SLOPE_PENALTY; #if DEBUG_SLUR_QUANTING (*scores)[i].score_card_ += to_string ("S%.2f",d); @@ -535,13 +852,6 @@ New_slur::get_curve (Grob*me) } - - - - -/* - ugh ? - */ MAKE_SCHEME_CALLBACK (New_slur, height, 2); SCM New_slur::height (SCM smob, SCM ax) @@ -559,7 +869,7 @@ New_slur::height (SCM smob, SCM ax) /* Ugh should have dash-length + dash-period - */ +*/ MAKE_SCHEME_CALLBACK (New_slur, print,1); SCM New_slur::print (SCM smob) @@ -577,15 +887,11 @@ New_slur::print (SCM smob) Real ss = Staff_symbol_referencer::staff_space (me); Bezier one = get_curve (me); - // get_curve may suicide - if (!scm_ilength (me->get_property ("note-columns"))) - return SCM_EOL; - Stencil a; /* TODO: replace dashed with generic property. - */ + */ SCM d = me->get_property ("dashed"); if (ly_c_number_p (d)) a = Lookup::dashed_slur (one, thick, thick * robust_scm2double (d, 0)); @@ -595,14 +901,15 @@ New_slur::print (SCM smob) #if DEBUG_SLUR_QUANTING SCM quant_score = me->get_property ("quant-score"); - if (// debug_beam_quanting_flag && + + if (to_boolean (me->get_paper ()->lookup_variable (ly_symbol2scm ("debug-slur-quanting"))) && ly_c_string_p (quant_score)) { String str; SCM properties = Font_interface::text_font_alist_chain (me); Stencil tm = *unsmob_stencil (Text_item::interpret_markup - (me->get_paper ()->self_scm (), properties, quant_score)); + (me->get_paper ()->self_scm (), properties, quant_score)); a.add_at_edge (Y_AXIS, get_grob_direction (me), tm, 1.0, 0); } #endif @@ -615,5 +922,5 @@ New_slur::print (SCM smob) ADD_INTERFACE (New_slur, "new-slur-interface", - "A slur", - "attachment attachment-offset beautiful control-points dashed details de-uglify-parameters direction extremity-function extremity-offset-alist height-limit note-columns ratio slope-limit thickness y-free"); + "A slur", + "control-points dashed details direction height-limit note-columns ratio slope-limit thickness");