X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fnote-collision.cc;h=7c43dddd4860bac3e2a608659ee92f0610d4e592;hb=322b487fc0042503777a9acbaa8bc96866ab0ae7;hp=a9b8cbe4410a466efad38433aeafa3c2c107098c;hpb=3f8a827aad721ed546b823e3f9f2605f61b90e20;p=lilypond.git diff --git a/lily/note-collision.cc b/lily/note-collision.cc index a9b8cbe441..7c43dddd48 100644 --- a/lily/note-collision.cc +++ b/lily/note-collision.cc @@ -1,7 +1,7 @@ /* This file is part of LilyPond, the GNU music typesetter. - Copyright (C) 1997--2011 Han-Wen Nienhuys + Copyright (C) 1997--2012 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 @@ -56,13 +56,35 @@ check_meshing_chords (Grob *me, Grob *head_up = Note_column::first_head (clash_up); Grob *head_down = Note_column::first_head (clash_down); - vector ups = Stem::note_head_positions (Note_column::get_stem (clash_up)); - vector dps = Stem::note_head_positions (Note_column::get_stem (clash_down)); + /* Staff-positions of all noteheads on each stem */ + vector ups = Stem::note_head_positions (stems[UP]); + vector dps = Stem::note_head_positions (stems[DOWN]); /* Too far apart to collide. */ if (ups[0] > dps.back () + 1) return; + /* If the chords just 'touch' their extreme noteheads, + then we can align their stems. + */ + bool touch = false; + if (ups[0] >= dps.back () + && (dps.size () < 2 || ups[0] >= dps[dps.size () - 2] + 2) + && (ups.size () < 2 || ups[1] >= dps.back () + 2)) + touch = true; + + /* Filter out the 'o's in this configuration, since they're no + * part in the collision. + * + * | + * x|o + * x|o + * x + * + */ + ups = Stem::note_head_positions (stems[UP], true); + dps = Stem::note_head_positions (stems[DOWN], true); + /* Merge heads if the notes lie the same line, or if the "stem-up-note" is above the "stem-down-note". */ bool merge_possible = (ups[0] >= dps[0]) && (ups.back () >= dps.back ()); @@ -118,16 +140,6 @@ check_meshing_chords (Grob *me, * */ - /* TODO: filter out the 'o's in this configuration, since they're no - * part in the collision. - * - * | - * x|o - * x|o - * x - * - */ - bool close_half_collide = false; bool distant_half_collide = false; bool full_collide = false; @@ -163,16 +175,6 @@ check_meshing_chords (Grob *me, full_collide = full_collide || (close_half_collide && distant_half_collide); - /* If the only collision is in the extreme noteheads, - then their stems can line up and the chords just 'touch'. - A half collision with the next note along the chord prevents touching. - */ - bool touch = false; - if (ups[0] >= dps.back () - && (dps.size () < 2 || ups[0] >= dps[dps.size () - 2] + 2) - && (ups.size () < 2 || ups[1] >= dps.back () + 2)) - touch = true; - /* Determine which chord goes on the left, and which goes right. Up-stem usually goes on the right, but if chords just 'touch' we can put both stems on a common vertical line. In the presense of collisions, @@ -306,32 +308,55 @@ check_meshing_chords (Grob *me, shift_amount *= 0.75; } - /* If the dotted notes ended up on the left, and there are collisions, - tell the Dot_Columnn to avoid the notes on the right. + /* If any dotted notes ended up on the left, + tell the Dot_Columnn to avoid the note heads on the right. */ - if (full_collide || close_half_collide || distant_half_collide) + if (shift_amount < -1e-6 + && Rhythmic_head::dot_count (head_up)) + { + Grob *d = unsmob_grob (head_up->get_object ("dot")); + Grob *parent = d->get_parent (X_AXIS); + if (Dot_column::has_interface (parent)) + Side_position_interface::add_support (parent, head_down); + } + else if (Rhythmic_head::dot_count (head_down)) { - if (shift_amount < -1e-6 - && Rhythmic_head::dot_count (head_up) - && !Rhythmic_head::dot_count (head_down)) + Grob *d = unsmob_grob (head_down->get_object ("dot")); + Grob *parent = d->get_parent (X_AXIS); + if (Dot_column::has_interface (parent)) { - Grob *d = unsmob_grob (head_up->get_object ("dot")); - Grob *parent = d->get_parent (X_AXIS); - if (Dot_column::has_interface (parent)) - Side_position_interface::add_support (parent, head_down); + Grob *stem = unsmob_grob (head_up->get_object ("stem")); + // Loop over all heads on an up-pointing-stem to see if dots + // need to clear any heads suspended on its right side. + extract_grob_set (stem, "note-heads", heads); + for (vsize i = 0; i < heads.size (); i++) + Side_position_interface::add_support (parent, heads[i]); } - else if (Rhythmic_head::dot_count (head_down) - && !Rhythmic_head::dot_count (head_up)) + } + + // In meshed chords with dots on the left, adjust dot direction + if (shift_amount > 1e-6 + && Rhythmic_head::dot_count (head_down)) + { + Grob *dot_down = unsmob_grob (head_down->get_object ("dot")); + Grob *col_down = dot_down->get_parent (X_AXIS); + Direction dir = UP; + if (Rhythmic_head::dot_count (head_up)) { - Grob *d = unsmob_grob (head_down->get_object ("dot")); - Grob *parent = d->get_parent (X_AXIS); - if (Dot_column::has_interface (parent)) - { - Grob *stem = unsmob_grob (head_up->get_object ("stem")); - extract_grob_set (stem, "note-heads", heads); - for (vsize i = 0; i < heads.size (); i++) - Side_position_interface::add_support (parent, heads[i]); - } + Grob *dot_up = unsmob_grob (head_up->get_object ("dot")); + Grob *col_up = dot_up->get_parent (X_AXIS); + if (col_up == col_down) // let the common DotColumn arrange dots + dir = CENTER; + else // conform to the dot direction on the up-stem chord + dir = robust_scm2dir (dot_up->get_property ("direction"), UP); + } + if (dir != CENTER) + { + Grob *stem = unsmob_grob (head_down->get_object ("stem")); + extract_grob_set (stem, "note-heads", heads); + for (vsize i = 0; i < heads.size (); i++) + unsmob_grob (heads[i]->get_object ("dot")) + ->set_property ("direction", scm_from_int (dir)); } } @@ -502,12 +527,12 @@ Note_collision_interface::automatic_shift (Grob *me, while ((flip (&d)) != UP); /* - do horizontal shifts of each direction - - | - x|| - x|| - x| + * do horizontal shifts of each direction + * + * | + * x|| + * x|| + * x| */ do