X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Ftie-formatting-problem.cc;h=bb50c4fbc18c1cfb9cee8be9fbb49e9c54b3b443;hb=64b22c2ebb52d0188fde41dc95832f2bc20c1147;hp=297fd4a1551ba33804939f6a770f6f7a4d2e6867;hpb=e832bb9391d6053f7328250ff1035376cf4b9d4b;p=lilypond.git diff --git a/lily/tie-formatting-problem.cc b/lily/tie-formatting-problem.cc index 297fd4a155..bb50c4fbc1 100644 --- a/lily/tie-formatting-problem.cc +++ b/lily/tie-formatting-problem.cc @@ -9,14 +9,15 @@ #include "tie-formatting-problem.hh" +#include "axis-group-interface.hh" #include "paper-column.hh" -#include "bezier.hh" +#include "bezier.hh" #include "directional-element-interface.hh" #include "libc-extension.hh" #include "misc.hh" #include "note-head.hh" #include "rhythmic-head.hh" -#include "spanner.hh" +#include "spanner.hh" #include "staff-symbol-referencer.hh" #include "stem.hh" #include "tie-configuration.hh" @@ -58,9 +59,11 @@ Tie_formatting_problem::get_attachment (Real y, Drul_array columns) const return attachments; } -Tie_formatting_problem::Tie_formatting_problem() +Tie_formatting_problem::Tie_formatting_problem () { x_refpoint_ = 0; + y_refpoint_ = 0; + use_horizontal_spacing_ = true; } Tie_formatting_problem::~Tie_formatting_problem () @@ -123,12 +126,24 @@ Tie_formatting_problem::set_column_chord_outline (vector bounds, { if (Stem::is_normal_stem (stem)) { - Interval x; x.add_point (stem->relative_coordinate (x_refpoint_, X_AXIS)); x.widen (staff_space / 20); // ugh. Interval y; - y.add_point (Stem::stem_end_position (stem) * staff_space * .5); + + Real stem_end_position = 0.0; + if (Stem::is_cross_staff (stem)) + stem_end_position = get_grob_direction (stem) * infinity_f; + else + { + if (use_horizontal_spacing_ || !Stem::get_beam (stem)) + stem_end_position = Stem::stem_end_position (stem) * staff_space * .5; + else + stem_end_position = Stem::note_head_positions (stem)[get_grob_direction (stem)] + * staff_space * .5; + } + + y.add_point (stem_end_position); Direction stemdir = get_grob_direction (stem); y.add_point (Stem::head_positions (stem)[-stemdir] @@ -139,12 +154,12 @@ Tie_formatting_problem::set_column_chord_outline (vector bounds, */ boxes.push_back (Box (x, y)); - stem_extents_[key].unite (Box (x,y)); + stem_extents_[key].unite (Box (x, y)); if (dir == LEFT) { Box flag_box = Stem::get_translated_flag (stem).extent_box (); - flag_box.translate( Offset (x[RIGHT], X_AXIS)); + flag_box.translate ( Offset (x[RIGHT], X_AXIS)); boxes.push_back (flag_box); } } @@ -158,6 +173,7 @@ Tie_formatting_problem::set_column_chord_outline (vector bounds, Real x_center = head->extent (x_refpoint_, X_AXIS).center (); Interval x_ext; x_ext[-dir] = x_center; + x_ext[dir] = infinity_f * dir; Interval y_ext; for (vsize j = 0; j < head_boxes.size (); j++) y_ext.unite (head_boxes[j][Y_AXIS]); @@ -166,26 +182,30 @@ Tie_formatting_problem::set_column_chord_outline (vector bounds, } extract_grob_set (stem, "note-heads", heads); - for (vsize i = 0; i < heads.size(); i ++) + for (vsize i = 0; i < heads.size (); i ++) { - if (find (bounds.begin(), bounds.end (), dynamic_cast (heads[i])) != bounds.end ()) - continue; - - /* - other untied notes in the same chord. - */ + if (find (bounds.begin (), bounds.end (), dynamic_cast (heads[i])) == bounds.end ()) + { + /* + other untied notes in the same chord. + */ - Interval y = Staff_symbol_referencer::extent_in_staff (heads[i]); - Interval x = heads[i]->extent (x_refpoint_, X_AXIS); - boxes.push_back (Box (x, y)); - + Interval y = Staff_symbol_referencer::extent_in_staff (heads[i]); + Interval x = heads[i]->extent (x_refpoint_, X_AXIS); + boxes.push_back (Box (x, y)); + } Grob *acc = unsmob_grob (heads[i]->get_object ("accidental-grob")); - if (acc && dir == RIGHT) + if (acc) + acc->get_property ("stencil"); /* trigger tie-related suicide */ + + if (acc && acc->is_live () && dir == RIGHT) { boxes.push_back (Box (acc->extent (x_refpoint_, X_AXIS), Staff_symbol_referencer::extent_in_staff (acc))); } + + head_positions_[column_rank].add_point (int (Staff_symbol_referencer::get_position (heads[i]))); } } @@ -195,7 +215,7 @@ Tie_formatting_problem::set_column_chord_outline (vector bounds, { Interval x; Interval y; - if (head_boxes.size()) + if (head_boxes.size ()) { Box b = boundary (head_boxes, updowndir, 0); x = b[X_AXIS]; @@ -213,9 +233,11 @@ Tie_formatting_problem::set_column_chord_outline (vector bounds, chord_outlines_[key] = Skyline (boxes, details_.skyline_padding_, Y_AXIS, -dir); if (bounds[0]->break_status_dir ()) { - Real x = robust_relative_extent (bounds[0], x_refpoint_, X_AXIS)[-dir]; - - chord_outlines_[key].set_minimum_height (x); + Interval iv (Axis_group_interface::staff_extent (bounds[0], x_refpoint_, X_AXIS, y_refpoint_, Y_AXIS)); + if (iv.is_empty ()) + iv.add_point (bounds[0]->relative_coordinate (x_refpoint_, X_AXIS)); + + chord_outlines_[key].set_minimum_height (iv[-dir]); } else { @@ -285,10 +307,20 @@ Tie_formatting_problem::from_ties (vector const &ties) return; x_refpoint_ = ties[0]; + y_refpoint_ = ties[0]; for (vsize i = 0; i < ties.size (); i++) { - x_refpoint_ = dynamic_cast (ties[i])->get_bound (LEFT)->common_refpoint (x_refpoint_, X_AXIS); - x_refpoint_ = dynamic_cast (ties[i])->get_bound (RIGHT)->common_refpoint (x_refpoint_, X_AXIS); + Spanner *tie = dynamic_cast (ties[i]); + Item *l = tie->get_bound (LEFT); + Item *r = tie->get_bound (RIGHT); + + x_refpoint_ = l->common_refpoint (x_refpoint_, X_AXIS); + x_refpoint_ = r->common_refpoint (x_refpoint_, X_AXIS); + + if (!l->break_status_dir ()) + y_refpoint_ = l->common_refpoint (y_refpoint_, Y_AXIS); + if (!r->break_status_dir ()) + y_refpoint_ = r->common_refpoint (y_refpoint_, Y_AXIS); } details_.from_grob (ties[0]); @@ -302,18 +334,9 @@ Tie_formatting_problem::from_ties (vector const &ties) { Item *it = dynamic_cast (ties[i])->get_bound (d); if (it->break_status_dir ()) - { - Item *sep - = dynamic_cast (unsmob_grob (ties[i]->get_object ("separation-item"))); - if (sep && sep->get_column () == it->get_column ()) - it = sep; + it = it->get_column (); - bounds.push_back (it); - } - else - { - bounds.push_back (it); - } + bounds.push_back (it); } set_chord_outline (bounds, d); @@ -341,7 +364,8 @@ Tie_formatting_problem::from_semi_ties (vector const &semi_ties, Directio { if (semi_ties.empty ()) return; - + + use_horizontal_spacing_ = false; details_.from_grob (semi_ties[0]); vector heads; @@ -368,11 +392,19 @@ Tie_formatting_problem::from_semi_ties (vector const &semi_ties, Directio specifications_.push_back (spec); } - x_refpoint_ = semi_ties [0]; + x_refpoint_ = semi_ties[0]; + y_refpoint_ = semi_ties[0]; + for (vsize i = 0; i < semi_ties.size (); i++) - x_refpoint_ = semi_ties[i]->common_refpoint (x_refpoint_, X_AXIS); + { + x_refpoint_ = semi_ties[i]->common_refpoint (x_refpoint_, X_AXIS); + y_refpoint_ = semi_ties[i]->common_refpoint (y_refpoint_, Y_AXIS); + } for (vsize i = 0; i < heads.size (); i++) - x_refpoint_ = heads[i]->common_refpoint (x_refpoint_, X_AXIS); + { + x_refpoint_ = heads[i]->common_refpoint (x_refpoint_, X_AXIS); + y_refpoint_ = heads[i]->common_refpoint (y_refpoint_, Y_AXIS) ; + } set_chord_outline (heads, head_dir); @@ -458,37 +490,41 @@ Tie_formatting_problem::generate_configuration (int pos, Direction dir, size. */ - if (h < details_.intra_space_threshold_ * 0.5 * details_.staff_space_) + if (head_positions_slice (columns[LEFT]).contains (pos) + || head_positions_slice (columns[RIGHT]).contains (pos) + || abs (pos) < 2 * Staff_symbol_referencer::staff_radius (details_.staff_symbol_referencer_)) { - if (!Staff_symbol_referencer::on_line (details_.staff_symbol_referencer_, pos) - && abs (pos) < 2 * Staff_symbol_referencer::staff_radius (details_.staff_symbol_referencer_)) + if (h < details_.intra_space_threshold_ * 0.5 * details_.staff_space_) { - conf->center_tie_vertically (details_); - } - else if (Staff_symbol_referencer::on_line (details_.staff_symbol_referencer_, pos)) - { - conf->delta_y_ += dir * - details_.tip_staff_line_clearance_ * 0.5 * details_.staff_space_; + if (!Staff_symbol_referencer::on_line (details_.staff_symbol_referencer_, pos) + && abs (pos) < 2 * Staff_symbol_referencer::staff_radius (details_.staff_symbol_referencer_)) + { + conf->center_tie_vertically (details_); + } + else if (Staff_symbol_referencer::on_line (details_.staff_symbol_referencer_, pos)) + { + conf->delta_y_ += dir * + details_.tip_staff_line_clearance_ * 0.5 * details_.staff_space_; + } } - } - else - { - Real top_y = y + conf->delta_y_ + conf->dir_ * h; - Real top_pos = top_y / (0.5*details_.staff_space_); - int round_pos = int (my_round (top_pos)); - - /* TODO: should use other variable? */ - Real clearance = details_.center_staff_line_clearance_; - if (fabs (top_pos - round_pos) < clearance - && Staff_symbol_referencer::on_staff_line (details_.staff_symbol_referencer_, - round_pos)) + else { - Real new_y = (round_pos + clearance * conf->dir_) * 0.5 * details_.staff_space_; - conf->delta_y_ = (new_y - top_y); + Real top_y = y + conf->delta_y_ + conf->dir_ * h; + Real top_pos = top_y / (0.5*details_.staff_space_); + int round_pos = int (my_round (top_pos)); + + /* TODO: should use other variable? */ + Real clearance = details_.center_staff_line_clearance_; + if (fabs (top_pos - round_pos) < clearance + && Staff_symbol_referencer::on_staff_line (details_.staff_symbol_referencer_, + round_pos)) + { + Real new_y = (round_pos + clearance * conf->dir_) * 0.5 * details_.staff_space_; + conf->delta_y_ = (new_y - top_y); + } } } - } - + } conf->attachment_x_ = get_attachment (y + conf->delta_y_, conf->column_ranks_); if (conf->height (details_) < details_.intra_space_threshold_ * 0.5 * details_.staff_space_) { @@ -574,7 +610,8 @@ Tie_formatting_problem::score_aptitude (Tie_configuration *conf, } { - Real p = details_.vertical_distance_penalty_factor_ * convex_amplifier (1.0, fabs (curve_y - tie_y)); + Real relevant_dist = max (fabs (curve_y - tie_y) - 0.5, 0.0); + Real p = details_.vertical_distance_penalty_factor_ * convex_amplifier (1.0, 0.9, relevant_dist); if (ties_conf) ties_conf->add_tie_score (p, tie_idx, "vdist"); else @@ -595,7 +632,7 @@ Tie_formatting_problem::score_aptitude (Tie_configuration *conf, TODO: flatten with log or sqrt. */ Real p = details_.horizontal_distance_penalty_factor_ - * convex_amplifier (1.25, dist); + * convex_amplifier (1.25, 1.0, dist); if (ties_conf) ties_conf->add_tie_score (p, tie_idx, (d == LEFT) ? "lhdist" : "rhdist"); @@ -606,7 +643,7 @@ Tie_formatting_problem::score_aptitude (Tie_configuration *conf, while (flip (&d) != LEFT); if (ties_conf - && ties_conf->size() == 1) + && ties_conf->size () == 1) { Direction d = LEFT; Drul_array stems (0, 0); @@ -646,6 +683,18 @@ Tie_formatting_problem::score_aptitude (Tie_configuration *conf, } +Slice +Tie_formatting_problem::head_positions_slice (int rank) const +{ + Position_extent_map::const_iterator i (head_positions_.find (rank)); + if (i != head_positions_.end ()) + { + return (*i).second; + } + Slice empty; + return empty; +} + /* Score a configuration, ie. how well these ties looks without regard to the note heads that they should connect to. @@ -682,9 +731,13 @@ Tie_formatting_problem::score_configuration (Tie_configuration *conf) const fabs (top_pos - round_top_pos)), "line center"); } - - if (Staff_symbol_referencer::on_line (details_.staff_symbol_referencer_, - int (rint (tip_pos)))) + + int rounded_tip_pos = int (rint (tip_pos)); + if (Staff_symbol_referencer::on_line (details_.staff_symbol_referencer_, rounded_tip_pos) + && (head_positions_slice (conf->column_ranks_[LEFT]).contains (rounded_tip_pos) + || head_positions_slice (conf->column_ranks_[RIGHT]).contains (rounded_tip_pos) + || abs (rounded_tip_pos) < 2 * Staff_symbol_referencer::staff_radius (details_.staff_symbol_referencer_)) + ) { conf->add_score (details_.staff_line_collision_penalty_ * peak_around (0.1 * details_.tip_staff_line_clearance_, @@ -1096,7 +1149,7 @@ Tie_formatting_problem::generate_collision_variations (Ties_configuration const ); vars.push_back (var); } - if (i == ties.size() && !specifications_[i].has_manual_position_ + if (i == ties.size () && !specifications_[i].has_manual_position_ && ties[i].dir_ == UP) { Tie_configuration_variation var; @@ -1168,7 +1221,7 @@ Tie_formatting_problem::set_debug_scoring (Ties_configuration const &base) if (to_boolean (x_refpoint_->layout () ->lookup_variable (ly_symbol2scm ("debug-tie-scoring")))) { - for (vsize i = 0; i < base.size(); i++) + for (vsize i = 0; i < base.size (); i++) { string card = base.complete_tie_card (i); specifications_[i].tie_grob_->set_property ("quant-score",