X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fslur-scoring.cc;h=a3dad6fb5e9785888b05b119ac5320b24c0b36b0;hb=b872748c6aa8bb721ced458691b38ac2fac5dfc8;hp=d8c7655185fd082796e3b20461faad75cde719a7;hpb=bb8aa1aed52c49e6e3de8c6c70a876598b11b4a8;p=lilypond.git diff --git a/lily/slur-scoring.cc b/lily/slur-scoring.cc index d8c7655185..a3dad6fb5e 100644 --- a/lily/slur-scoring.cc +++ b/lily/slur-scoring.cc @@ -1,7 +1,7 @@ /* This file is part of LilyPond, the GNU music typesetter. - Copyright (C) 1996--2011 Han-Wen Nienhuys + Copyright (C) 1996--2015 Han-Wen Nienhuys Jan Nieuwenhuizen LilyPond is free software: you can redistribute it and/or modify @@ -22,14 +22,17 @@ #include +#include "axis-group-interface.hh" #include "accidental-interface.hh" #include "beam.hh" #include "clef.hh" #include "directional-element-interface.hh" +#include "dots.hh" #include "libc-extension.hh" #include "main.hh" #include "misc.hh" #include "note-column.hh" +#include "note-head.hh" #include "output-def.hh" #include "paper-column.hh" #include "pitch.hh" @@ -40,7 +43,6 @@ #include "staff-symbol-referencer.hh" #include "staff-symbol.hh" #include "stem.hh" -#include "time-signature.hh" #include "warn.hh" /* @@ -105,7 +107,7 @@ Slur_score_state::slur_direction () const Encompass_info Slur_score_state::get_encompass_info (Grob *col) const { - Grob *stem = unsmob_grob (col->get_object ("stem")); + Grob *stem = unsmob (col->get_object ("stem")); Encompass_info ei; if (!stem) @@ -155,16 +157,17 @@ Slur_score_state::get_bound_info () const { Drul_array extremes; - Direction d = LEFT; Direction dir = dir_; - do + for (LEFT_and_RIGHT (d)) { extremes[d].bound_ = slur_->get_bound (d); - if (Note_column::has_interface (extremes[d].bound_)) + if (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].flag_ = Note_column::get_flag (extremes[d].note_column_); + if (extremes[d].stem_) { extremes[d].stem_dir_ = get_grob_direction (extremes[d].stem_); @@ -173,6 +176,8 @@ Slur_score_state::get_bound_info () const { Axis ax = Axis (a); Interval s = extremes[d].stem_->extent (common_[ax], ax); + if (extremes[d].flag_) + s.unite (extremes[d].flag_->extent (common_[ax], ax)); if (s.is_empty ()) { /* @@ -196,13 +201,15 @@ Slur_score_state::get_bound_info () const ::staff_space (extremes[d].stem_); } - if (extremes[d].slur_head_) - extremes[d].slur_head_x_extent_ - = extremes[d].slur_head_->extent (common_[X_AXIS], X_AXIS); - } + else if (has_interface (extremes[d].bound_)) + { + extremes[d].slur_head_ = extremes[d].bound_; + } + if (extremes[d].slur_head_) + extremes[d].slur_head_x_extent_ + = extremes[d].slur_head_->extent (common_[X_AXIS], X_AXIS); } - while (flip (&d) != LEFT); return extremes; } @@ -222,8 +229,8 @@ Slur_score_state::fill (Grob *me) Slur::replace_breakable_encompass_objects (me); staff_space_ = Staff_symbol_referencer::staff_space (me); - Real lt = me->layout ()->get_dimension (ly_symbol2scm ("line-thickness")); - thickness_ = robust_scm2double (me->get_property ("thickness"), 1.0) * lt; + line_thickness_ = me->layout ()->get_dimension (ly_symbol2scm ("line-thickness")); + thickness_ = robust_scm2double (me->get_property ("thickness"), 1.0) * line_thickness_; dir_ = slur_direction (); parameters_.fill (me); @@ -239,8 +246,7 @@ Slur_score_state::fill (Grob *me) common_[a] = common_refpoint_of_array (columns, me, a); common_[a] = common_refpoint_of_array (extra_objects, common_[a], a); - Direction d = LEFT; - do + for (LEFT_and_RIGHT (d)) { /* If bound is not in note-columns, we don't want to know about @@ -249,12 +255,11 @@ Slur_score_state::fill (Grob *me) if (a != Y_AXIS) common_[a] = common_[a]->common_refpoint (sp->get_bound (d), a); } - while (flip (&d) != LEFT); } extremes_ = get_bound_info (); - is_broken_ = (!extremes_[LEFT].note_column_ - || !extremes_[RIGHT].note_column_); + is_broken_ = (!(extremes_[LEFT].note_column_ || extremes_[LEFT].slur_head_) + || !(extremes_[RIGHT].note_column_ || extremes_[RIGHT].slur_head_)); has_same_beam_ = (extremes_[LEFT].stem_ && extremes_[RIGHT].stem_ @@ -267,7 +272,7 @@ Slur_score_state::fill (Grob *me) extra_encompass_infos_ = get_extra_encompass_infos (); - Interval additional_ys (0.0,0.0); + Interval additional_ys (0.0, 0.0); for (vsize i = 0; i < extra_encompass_infos_.size (); i++) { @@ -280,31 +285,28 @@ Slur_score_state::fill (Grob *me) end_ys[RIGHT], end_ys[LEFT]); Real encompass_place = extra_encompass_infos_[i].extents_[Y_AXIS][dir_]; - if (extra_encompass_infos_[i].type_ == ly_symbol2scm ("inside") + if (scm_is_eq (extra_encompass_infos_[i].type_, + ly_symbol2scm ("inside")) && minmax (dir_, encompass_place, y_place) == encompass_place && (!extra_encompass_infos_[i].grob_->internal_has_interface (ly_symbol2scm ("key-signature-interface")) - && !Clef::has_interface (extra_encompass_infos_[i].grob_) - && !Time_signature::has_interface (extra_encompass_infos_[i].grob_))) + && !has_interface (extra_encompass_infos_[i].grob_) + && !extra_encompass_infos_[i].grob_->internal_has_interface (ly_symbol2scm ("time-signature-interface")))) { - Direction d = LEFT; - do + for (LEFT_and_RIGHT (d)) additional_ys[d] = minmax (dir_, additional_ys[d], (dir_ * (parameters_.encompass_object_range_overshoot_ + (y_place - encompass_place) - * (normalize (extra_encompass_infos_[i].extents_[X_AXIS].center (), - base_attachments_[RIGHT][X_AXIS], - base_attachments_[LEFT][X_AXIS]) - + (dir_ == LEFT ? 0 : -1))))); - while (flip (&d) != LEFT); + * (normalize (extra_encompass_infos_[i].extents_[X_AXIS].center (), + base_attachments_[RIGHT][X_AXIS], + base_attachments_[LEFT][X_AXIS]) + + (dir_ == LEFT ? 0 : -1))))); } } - Direction d = LEFT; - do + for (LEFT_and_RIGHT (d)) end_ys[d] += additional_ys[d]; - while (flip (&d) != LEFT); configurations_ = enumerate_attachments (end_ys); for (vsize i = 0; i < columns_.size (); i++) @@ -313,14 +315,13 @@ Slur_score_state::fill (Grob *me) valid_ = true; musical_dy_ = 0.0; - do + for (LEFT_and_RIGHT (d)) { if (!is_broken_ && extremes_[d].slur_head_) musical_dy_ += d * extremes_[d].slur_head_->relative_coordinate (common_[Y_AXIS], Y_AXIS); } - while (flip (&d) != LEFT); edge_has_beams_ = (extremes_[LEFT].stem_ && Stem::get_beam (extremes_[LEFT].stem_)) @@ -334,7 +335,7 @@ MAKE_SCHEME_CALLBACK (Slur, calc_control_points, 1) SCM Slur::calc_control_points (SCM smob) { - Spanner *me = unsmob_spanner (smob); + Spanner *me = unsmob (smob); Slur_score_state state; state.fill (me); @@ -430,10 +431,12 @@ Slur_score_state::get_best_curve () const return best; } -Grob * -Slur_score_state::breakable_bound_item (Direction d) const +Interval +Slur_score_state::breakable_bound_extent (Direction d) const { Grob *col = slur_->get_bound (d)->get_column (); + Interval ret; + ret.set_empty (); extract_grob_set (slur_, "encompass-objects", extra_encompasses); @@ -441,10 +444,10 @@ Slur_score_state::breakable_bound_item (Direction d) const { Item *item = dynamic_cast (extra_encompasses[i]); if (item && col == item->get_column ()) - return item; + ret.unite (robust_relative_extent (item, common_[X_AXIS], X_AXIS)); } - return 0; + return ret; } /* @@ -456,21 +459,29 @@ Drul_array Slur_score_state::get_y_attachment_range () const { Drul_array end_ys; - Direction d = LEFT; - do + for (LEFT_and_RIGHT (d)) { if (extremes_[d].note_column_) { - end_ys[d] = dir_ - * max (max (dir_ * (base_attachments_[d][Y_AXIS] - + parameters_.region_size_ * dir_), - dir_ * (dir_ + extremes_[d].note_column_->extent (common_[Y_AXIS], Y_AXIS)[dir_])), - dir_ * base_attachments_[-d][Y_AXIS]); + Interval nc_extent = extremes_[d].note_column_ + ->extent (common_[Y_AXIS], Y_AXIS); + if (nc_extent.is_empty ()) + slur_->warning ("slur trying to encompass an empty note column."); + else + end_ys[d] = dir_ + * max (max (dir_ * (base_attachments_[d][Y_AXIS] + + parameters_.region_size_ * dir_), + dir_ * (dir_ + nc_extent[dir_])), + dir_ * base_attachments_[-d][Y_AXIS]); + } + else if (extremes_[d].slur_head_) + { + // allow only minimal movement + end_ys[d] = base_attachments_[d][Y_AXIS] + 0.3 * dir_; } else end_ys[d] = base_attachments_[d][Y_AXIS] + parameters_.region_size_ * dir_; } - while (flip (&d) != LEFT); return end_ys; } @@ -479,13 +490,11 @@ bool spanner_less (Spanner *s1, Spanner *s2) { Slice b1, b2; - Direction d = LEFT; - do + for (LEFT_and_RIGHT (d)) { b1[d] = s1->get_bound (d)->get_column ()->get_rank (); b2[d] = s2->get_bound (d)->get_column ()->get_rank (); } - while (flip (&d) != LEFT); return b2[LEFT] <= b1[LEFT] && b2[RIGHT] >= b1[RIGHT] && (b2[LEFT] != b1[LEFT] || b2[RIGHT] != b1[RIGHT]); @@ -495,8 +504,7 @@ Drul_array Slur_score_state::get_base_attachments () const { Drul_array base_attachment; - Direction d = LEFT; - do + for (LEFT_and_RIGHT (d)) { Grob *stem = extremes_[d].stem_; Grob *head = extremes_[d].slur_head_; @@ -529,25 +537,32 @@ Slur_score_state::get_base_attachments () const : extremes_[d].bound_->extent (common_[X_AXIS], X_AXIS)) .linear_combination (CENTER); } + else if (head) + { + y = head->extent (common_[Y_AXIS], Y_AXIS) + .linear_combination (0.5*dir_); + + // Don't "move_away_from_staffline" because that makes it + // harder to recognize the specific attachment point + x = head->extent (common_[X_AXIS], X_AXIS)[-d]; + } + base_attachment[d] = Offset (x, y); } - while (flip (&d) != LEFT); - do + for (LEFT_and_RIGHT (d)) { - if (!extremes_[d].note_column_) + if (!extremes_[d].note_column_ && !extremes_[d].slur_head_) { Real x = 0; Real y = 0; - if (Grob *g = breakable_bound_item (d)) - { - x = robust_relative_extent (g, common_[X_AXIS], X_AXIS)[RIGHT]; - } - else if (d == RIGHT) - x = robust_relative_extent (extremes_[d].bound_, common_[X_AXIS], X_AXIS)[d]; - else - x = slur_->get_broken_left_end_align (); + Interval ext = breakable_bound_extent (d); + if (ext.is_empty ()) + ext = Axis_group_interface:: + generic_bound_extent (extremes_[d].bound_, + common_[X_AXIS], X_AXIS); + x = ext[-d]; Grob *col = (d == LEFT) ? columns_[0] : columns_.back (); @@ -569,9 +584,8 @@ Slur_score_state::get_base_attachments () const base_attachment[d] = Offset (x, y); } } - while (flip (&d) != LEFT); - do + for (LEFT_and_RIGHT (d)) { for (int a = X_AXIS; a < NO_AXES; a++) { @@ -584,7 +598,6 @@ Slur_score_state::get_base_attachments () const } } } - while (flip (&d) != LEFT); return base_attachment; } @@ -606,8 +619,7 @@ Slur_score_state::move_away_from_staffline (Real y, * 2.0 / staff_space_; if (fabs (pos - my_round (pos)) < 0.2 - && Staff_symbol_referencer::on_line (on_staff, (int) rint (pos)) - && Staff_symbol_referencer::line_count (on_staff) - 1 >= rint (pos)) + && Staff_symbol_referencer::on_staff_line (on_staff, (int) rint (pos))) y += 1.5 * staff_space_ * dir_ / 10; return y; @@ -634,7 +646,7 @@ Slur_score_state::generate_avoid_offsets () const extract_grob_set (slur_, "encompass-objects", extra_encompasses); for (vsize i = 0; i < extra_encompasses.size (); i++) { - if (Slur::has_interface (extra_encompasses[i])) + if (has_interface (extra_encompasses[i])) { Grob *small_slur = extra_encompasses[i]; Bezier b = Slur::get_curve (small_slur); @@ -646,7 +658,8 @@ Slur_score_state::generate_avoid_offsets () const z[Y_AXIS] += dir_ * parameters_.free_slur_distance_; avoid.push_back (z); } - else if (extra_encompasses[i]->get_property ("avoid-slur") == ly_symbol2scm ("inside")) + else if (scm_is_eq (extra_encompasses[i]->get_property ("avoid-slur"), + ly_symbol2scm ("inside"))) { Grob *g = extra_encompasses [i]; Interval xe = g->extent (common_[X_AXIS], X_AXIS); @@ -686,9 +699,9 @@ 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++) { - Direction d = LEFT; + Drul_array attach_to_stem (false, false); - do + for (LEFT_and_RIGHT (d)) { os[d][X_AXIS] = base_attachments_[d][X_AXIS]; if (extremes_[d].stem_ @@ -710,14 +723,13 @@ Slur_score_state::enumerate_attachments (Drul_array end_ys) const os[d][X_AXIS] = extremes_[d].stem_extent_[X_AXIS].center (); } } - while (flip (&d) != LEFT); Offset dz; dz = os[RIGHT] - os[LEFT]; if (dz[X_AXIS] < minimum_length || fabs (dz[Y_AXIS] / dz[X_AXIS]) > parameters_.max_slope_) { - do + for (LEFT_and_RIGHT (d)) { if (extremes_[d].slur_head_ && !extremes_[d].slur_head_x_extent_.is_empty ()) @@ -726,11 +738,10 @@ Slur_score_state::enumerate_attachments (Drul_array end_ys) const attach_to_stem[d] = false; } } - while (flip (&d) != LEFT); } - dz = os[RIGHT] - os[LEFT]; - do + dz = (os[RIGHT] - os[LEFT]).direction (); + for (LEFT_and_RIGHT (d)) { if (extremes_[d].slur_head_ && !attach_to_stem[d]) @@ -741,10 +752,9 @@ Slur_score_state::enumerate_attachments (Drul_array end_ys) const TODO: parameter */ os[d][X_AXIS] -= dir_ * extremes_[d].slur_head_x_extent_.length () - * sin (dz.arg ()) / 3; + * dz[Y_AXIS] / 3; } } - while (flip (&d) != LEFT); scores.push_back (Slur_configuration::new_config (os, scores.size ())); @@ -765,7 +775,7 @@ Slur_score_state::get_extra_encompass_infos () const vector collision_infos; for (vsize i = encompasses.size (); i--;) { - if (Slur::has_interface (encompasses[i])) + if (has_interface (encompasses[i])) { Spanner *small_slur = dynamic_cast (encompasses[i]); Bezier b = Slur::get_curve (small_slur); @@ -806,10 +816,12 @@ Slur_score_state::get_extra_encompass_infos () const Grob *g = encompasses [i]; Interval xe = g->extent (common_[X_AXIS], X_AXIS); Interval ye = g->extent (common_[Y_AXIS], Y_AXIS); + if (has_interface (g)) + ye.widen (0.2); Real xp = 0.0; Real penalty = parameters_.extra_object_collision_penalty_; - if (Accidental_interface::has_interface (g)) + if (has_interface (g)) { penalty = parameters_.accidental_collision_;