X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fnote-spacing.cc;h=a894be25394c9a41ba44a5db8870e79e686c574b;hb=97a0169312a260933246ab224e4f8b0969871dd5;hp=076d34648d37036de3886984231fc5057970dd55;hpb=190a067275167c6dc9dd0afef683d14d392b7033;p=lilypond.git diff --git a/lily/note-spacing.cc b/lily/note-spacing.cc index 076d34648d..a894be2539 100644 --- a/lily/note-spacing.cc +++ b/lily/note-spacing.cc @@ -1,7 +1,7 @@ /* This file is part of LilyPond, the GNU music typesetter. - Copyright (C) 2001--2010 Han-Wen Nienhuys + Copyright (C) 2001--2015 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 @@ -31,17 +31,17 @@ #include "separation-item.hh" #include "spacing-interface.hh" #include "staff-spacing.hh" +#include "staff-symbol-referencer.hh" #include "stem.hh" #include "warn.hh" /* - TODO: detect hshifts due to collisions, and account for them in - spacing? + Adjust the ideal and minimum distance between note columns, + based on the notehead size, skylines, and optical illusions. */ - Spring Note_spacing::get_spacing (Grob *me, Item *right_col, - Real base_space, Real increment) + Spring base, Real increment) { vector note_columns = Spacing_interface::left_note_columns (me); Real left_head_end = 0; @@ -49,39 +49,35 @@ Note_spacing::get_spacing (Grob *me, Item *right_col, for (vsize i = 0; i < note_columns.size (); i++) { SCM r = note_columns[i]->get_object ("rest"); - Grob *g = unsmob_grob (r); + Grob *g = unsmob (r); Grob *col = note_columns[i]->get_column (); if (!g) - g = Note_column::first_head (note_columns[i]); + g = Note_column::first_head (note_columns[i]); /* - Ugh. If Stem is switched off, we don't know what the - first note head will be. + Ugh. If Stem is switched off, we don't know what the + first note head will be. */ if (g) - { - if (g->common_refpoint (col, X_AXIS) != col) - programming_error ("Note_spacing::get_spacing (): Common refpoint incorrect"); - else - left_head_end = g->extent (col, X_AXIS)[RIGHT]; - } + { + if (g->common_refpoint (col, X_AXIS) != col) + programming_error ("Note_spacing::get_spacing (): Common refpoint incorrect"); + else + left_head_end = g->extent (col, X_AXIS)[RIGHT]; + } } /* The main factor that determines the amount of space is the width of the note head (or the rest). For example, a quarter rest gets almost 0.5 ss less horizontal space than a note. - - The other parts of a note column (eg. flags, accidentals, etc.) don't get - the full amount of space. We give them half the amount of space, but then - adjust things so there are no collisions. */ + Real ideal = base.distance () - increment + left_head_end; Drul_array skys = Spacing_interface::skylines (me, right_col); - Real distance = skys[LEFT].distance (skys[RIGHT]); + Real distance = skys[LEFT].distance (skys[RIGHT], robust_scm2double (right_col->get_property ("skyline-vertical-padding"), 0.0)); Real min_dist = max (0.0, distance); - Real min_desired_space = left_head_end + (min_dist - left_head_end + base_space - increment) / 2; - Real ideal = base_space - increment + left_head_end; + base.set_min_distance (min_dist); /* If we have a NonMusical column on the right, we measure the ideal distance to the bar-line (if present), not the start of the column. */ @@ -90,28 +86,25 @@ Note_spacing::get_spacing (Grob *me, Item *right_col, && to_boolean (me->get_property ("space-to-barline"))) { Grob *bar = Pointer_group_interface::find_grob (right_col, - ly_symbol2scm ("elements"), - Bar_line::non_empty_barline); + ly_symbol2scm ("elements"), + Bar_line::non_empty_barline); if (bar) - { - Real shift = bar->extent (right_col, X_AXIS)[LEFT]; - ideal -= shift; - min_desired_space -= max (shift, 0.0); - } + ideal -= bar->extent (right_col, X_AXIS)[LEFT]; else - ideal -= right_col->extent (right_col, X_AXIS)[RIGHT]; + { + /* Measure ideal distance to the right side of the NonMusical column + but keep at least half the gap we would have had to a note */ + Real min_desired_space = (ideal + min_dist) / 2.0; + ideal -= right_col->extent (right_col, X_AXIS)[RIGHT]; + ideal = max (ideal, min_desired_space); + } } - ideal = max (ideal, min_desired_space); - stem_dir_correction (me, right_col, increment, &ideal, &min_desired_space); + stem_dir_correction (me, right_col, increment, &ideal); - /* TODO: grace notes look bad when things are stretched. Should we increase - their stretch strength? */ - Spring ret (max (0.0, ideal), min_dist); - ret.set_inverse_compress_strength (max (0.0, ideal - min_desired_space)); - ret.set_inverse_stretch_strength (max (0.1, base_space - increment)); - return ret; + base.set_distance (max (0.0, ideal)); + return base; } static Real @@ -127,19 +120,19 @@ knee_correction (Grob *note_spacing, Grob *right_stem, Real increment) head_extent = head->extent (rcolumn, X_AXIS); if (!head_extent.is_empty ()) - note_head_width = head_extent[RIGHT]; + note_head_width = head_extent[RIGHT]; note_head_width -= Stem::thickness (right_stem); } return -note_head_width * get_grob_direction (right_stem) - * robust_scm2double (note_spacing->get_property ("knee-spacing-correction"), 0); + * robust_scm2double (note_spacing->get_property ("knee-spacing-correction"), 0); } static Real different_directions_correction (Grob *note_spacing, - Drul_array stem_posns, - Direction left_stem_dir) + Drul_array stem_posns, + Direction left_stem_dir) { Real ret = 0.0; Interval intersect = stem_posns[LEFT]; @@ -150,11 +143,11 @@ different_directions_correction (Grob *note_spacing, ret = abs (intersect.length ()); /* - Ugh. 7 is hardcoded. + Ugh. 7 is hardcoded. */ ret = min (ret / 7, 1.0) - * left_stem_dir - * robust_scm2double (note_spacing->get_property ("stem-spacing-correction"), 0); + * left_stem_dir + * robust_scm2double (note_spacing->get_property ("stem-spacing-correction"), 0); } return ret; } @@ -204,14 +197,14 @@ same_direction_correction (Grob *note_spacing, Drul_array head_posns) */ void Note_spacing::stem_dir_correction (Grob *me, Item *rcolumn, - Real increment, - Real *space, Real *fixed) + Real increment, + Real *space) { Drul_array stem_dirs (CENTER, CENTER); Drul_array stem_posns; Drul_array head_posns; Drul_array props (me->get_object ("left-items"), - me->get_object ("right-items")); + me->get_object ("right-items")); Drul_array beams_drul (0, 0); Drul_array stems_drul (0, 0); @@ -221,74 +214,62 @@ Note_spacing::stem_dir_correction (Grob *me, Item *rcolumn, Interval bar_xextent; Interval bar_yextent; - Direction d = LEFT; - bool acc_right = false; Grob *bar = Spacing_interface::extremal_break_aligned_grob (me, RIGHT, - rcolumn->break_status_dir (), - &bar_xextent); + rcolumn->break_status_dir (), + &bar_xextent); if (bar && dynamic_cast (bar)->get_column () == rcolumn) bar_yextent = Staff_spacing::bar_y_positions (bar); - do + for (LEFT_and_RIGHT (d)) { vector const &items (ly_scm2link_array (props [d])); for (vsize i = 0; i < items.size (); i++) - { - Item *it = dynamic_cast (items[i]); - if (!Note_column::has_interface (it)) - continue; - if (d == RIGHT && it->get_column () != rcolumn) - continue; - - /* - Find accidentals which are sticking out of the right side. - */ - if (d == RIGHT) - acc_right = acc_right || Note_column::accidentals (it); - - Grob *stem = Note_column::get_stem (it); - - if (!stem || !stem->is_live () || Stem::is_invisible (stem)) - return; - - stems_drul[d] = stem; - beams_drul[d] = Stem::get_beam (stem); - - Direction stem_dir = get_grob_direction (stem); - if (stem_dirs[d] && stem_dirs[d] != stem_dir) - return; - - stem_dirs[d] = stem_dir; - - /* - Correction doesn't seem appropriate when there is a large flag - hanging from the note. - */ - if (d == LEFT - && Stem::duration_log (stem) > 2 && !Stem::get_beam (stem)) - return; - - Interval hp = Stem::head_positions (stem); - if (!hp.is_empty ()) - { - Real chord_start = hp[stem_dir]; - - /* - can't look at stem-end-position, since that triggers - beam slope computations. - */ - Real stem_end = hp[stem_dir] - + stem_dir * robust_scm2double (stem->get_property ("length"), 7); - - stem_posns[d] = Interval (min (chord_start, stem_end), - max (chord_start, stem_end)); - head_posns[d].unite (hp); - } - } + { + Item *it = dynamic_cast (items[i]); + if (!has_interface (it)) + continue; + if (d == RIGHT && it->get_column () != rcolumn) + continue; + + /* + Find accidentals which are sticking out of the right side. + */ + if (d == RIGHT) + acc_right = acc_right || Note_column::accidentals (it); + + Grob *stem = Note_column::get_stem (it); + + if (!stem || !stem->is_live () || Stem::is_invisible (stem)) + return; + + stems_drul[d] = stem; + beams_drul[d] = Stem::get_beam (stem); + + Direction stem_dir = get_grob_direction (stem); + if (stem_dirs[d] && stem_dirs[d] != stem_dir) + return; + + stem_dirs[d] = stem_dir; + + /* + Correction doesn't seem appropriate when there is a large flag + hanging from the note. + */ + if (d == LEFT + && Stem::duration_log (stem) > 2 && !Stem::get_beam (stem)) + return; + + Interval hp = Stem::head_positions (stem); + if (!hp.is_empty ()) + { + Real ss = Staff_symbol_referencer::staff_space (stem); + stem_posns[d] = stem->pure_y_extent (stem, 0, INT_MAX) * (2 / ss); + head_posns[d].unite (hp); + } + } } - while (flip (&d) != LEFT); Real correction = 0.0; @@ -302,24 +283,23 @@ Note_spacing::stem_dir_correction (Grob *me, Item *rcolumn, if (stem_dirs[LEFT] * stem_dirs[RIGHT] == -1) { if (beams_drul[LEFT] && beams_drul[LEFT] == beams_drul[RIGHT]) - { - correction = knee_correction (me, stems_drul[RIGHT], increment); - *fixed += correction; - } + { + correction = knee_correction (me, stems_drul[RIGHT], increment); + } else - { - correction = different_directions_correction (me, stem_posns, stem_dirs[LEFT]); + { + correction = different_directions_correction (me, stem_posns, stem_dirs[LEFT]); - if (!bar_yextent.is_empty ()) - correction *= 0.5; - } + if (!bar_yextent.is_empty ()) + correction *= 0.5; + } } /* Only apply same direction correction if there are no accidentals sticking out of the right hand side. */ else if (stem_dirs[LEFT] * stem_dirs[RIGHT] == 1 - && !acc_right) + && !acc_right) correction = same_direction_correction (me, head_posns); *space += correction; @@ -330,14 +310,14 @@ Note_spacing::stem_dir_correction (Grob *me, Item *rcolumn, } ADD_INTERFACE (Note_spacing, - "This object calculates spacing wishes for individual voices.", - - /* properties */ - "knee-spacing-correction " - "left-items " - "right-items " - "same-direction-correction " - "stem-spacing-correction " - "space-to-barline " - ); + "This object calculates spacing wishes for individual voices.", + + /* properties */ + "knee-spacing-correction " + "left-items " + "right-items " + "same-direction-correction " + "stem-spacing-correction " + "space-to-barline " + );