X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fnote-collision.cc;h=b0049c69ea40300d73427d1808324c94b8addb08;hb=e90f0536f9be39ada0bef0aeb0d275dec3b2fb5b;hp=6946eac2fa786420e5e080a70ec65978f0a180b8;hpb=0e5d83a9ceb4a143f83d22406d7eb816314ff9f7;p=lilypond.git diff --git a/lily/note-collision.cc b/lily/note-collision.cc index 6946eac2fa..b0049c69ea 100644 --- a/lily/note-collision.cc +++ b/lily/note-collision.cc @@ -1,9 +1,20 @@ /* - collision.cc -- implement Collision + This file is part of LilyPond, the GNU music typesetter. - source file of the GNU LilyPond music typesetter + Copyright (C) 1997--2011 Han-Wen Nienhuys - (c) 1997--2009 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 + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + LilyPond is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with LilyPond. If not, see . */ #include "note-collision.hh" @@ -30,7 +41,7 @@ check_meshing_chords (Grob *me, Drul_array > const &clash_groups) { - if (!extents[UP].size () || ! extents[DOWN].size ()) + if (!extents[UP].size () || !extents[DOWN].size ()) return; Grob *clash_up = clash_groups[UP][0]; @@ -42,14 +53,14 @@ check_meshing_chords (Grob *me, Drul_array stems (Note_column::get_stem (clash_down), Note_column::get_stem (clash_up)); - + 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)); - /* Too far apart to collide. */ + /* Too far apart to collide. */ if (ups[0] > dps.back () + 1) return; @@ -65,7 +76,7 @@ check_meshing_chords (Grob *me, int up_ball_type = Rhythmic_head::duration_log (head_up); int down_ball_type = Rhythmic_head::duration_log (head_down); - /* Do not merge whole notes (or longer, like breve, longa, maxima). */ + /* Do not merge whole notes (or longer, like breve, longa, maxima). */ if (merge_possible && (up_ball_type <= 0 || down_ball_type <= 0)) merge_possible = false; @@ -74,8 +85,7 @@ check_meshing_chords (Grob *me, && !to_boolean (me->get_property ("merge-differently-dotted"))) merge_possible = false; - /* Can only merge different heads if merge-differently-headed is - set. */ + /* Can only merge different heads if merge-differently-headed is set. */ if (merge_possible && up_ball_type != down_ball_type && !to_boolean (me->get_property ("merge-differently-headed"))) @@ -154,10 +164,6 @@ check_meshing_chords (Grob *me, full_collide = full_collide || (close_half_collide && distant_half_collide); - Drul_array center_note_shifts; - center_note_shifts[LEFT] = 0.0; - center_note_shifts[RIGHT] = 0.0; - Real shift_amount = 1; bool touch = (ups[0] >= dps.back ()); @@ -172,7 +178,7 @@ check_meshing_chords (Grob *me, shift_amount *= -1; /* For full collisions, the right hand head may obscure dots, so - make sure the dotted heads go to the right. */ + make sure the dotted heads go to the right. */ bool stem_to_stem = false; if (full_collide) { @@ -183,24 +189,26 @@ check_meshing_chords (Grob *me, } /* The solfa is a triangle, which is inverted depending on stem - direction. In case of a collision, one of them should be removed, + direction. In case of a collision, one of them should be removed, so the resulting note does not look like a block. */ + SCM up_style = head_up->get_property ("style"); + SCM down_style = head_down->get_property ("style"); if (merge_possible - && head_up->get_property ("style") == ly_symbol2scm ("fa") - && head_down->get_property ("style") == ly_symbol2scm ("fa")) + && (up_style == ly_symbol2scm ("fa") || up_style == ly_symbol2scm ("faThin")) + && (down_style == ly_symbol2scm ("fa") || down_style == ly_symbol2scm ("faThin"))) { Interval uphead_size = head_up->extent (head_up, Y_AXIS); Offset att = Offset (0.0, -1.0); head_up->set_property ("stem-attachment", ly_offset2scm (att)); - head_up->set_property ("transparent", SCM_BOOL_T); + head_up->set_property ("transparent", SCM_BOOL_T); } - + if (merge_possible) { shift_amount = 0; - /* If possible, don't wipe any heads. Else, wipe shortest head, + /* If possible, don't wipe any heads. Else, wipe shortest head, or head with smallest amount of dots. Note: when merging different heads, dots on the smaller one disappear. */ Grob *wipe_ball = 0; @@ -230,6 +238,15 @@ check_meshing_chords (Grob *me, { wipe_ball = head_up; dot_wipe_head = head_up; + /* + If upper head is eighth note or shorter, and lower head is half note, + shift by the difference between the open and filled note head widths, + otherwise upper stem will be misaligned slightly. + */ + if (Stem::duration_log (stems[DOWN]) == 1 + && Stem::duration_log (stems[UP]) >= 3) + shift_amount = (1 - head_up->extent (head_up, X_AXIS).length () / + head_down->extent (head_down, X_AXIS).length ()) * 0.5; } if (dot_wipe_head) @@ -239,12 +256,10 @@ check_meshing_chords (Grob *me, } if (wipe_ball && wipe_ball->is_live ()) - { - wipe_ball->set_property ("transparent", SCM_BOOL_T); - } + wipe_ball->set_property ("transparent", SCM_BOOL_T); } /* TODO: these numbers are magic; should devise a set of grob props - to tune this behavior. */ + to tune this behavior. */ else if (stem_to_stem) shift_amount = -abs (shift_amount) * 0.65; else if (close_half_collide && !touch) @@ -254,14 +269,14 @@ check_meshing_chords (Grob *me, else if (distant_half_collide || close_half_collide || full_collide) shift_amount *= 0.5; - /* we're meshing. */ + /* we're meshing. */ else if (Rhythmic_head::dot_count (head_up) || Rhythmic_head::dot_count (head_down)) shift_amount *= 0.1; else shift_amount *= 0.17; /* - + */ if (full_collide && down_ball_type * up_ball_type == 0) @@ -275,7 +290,7 @@ check_meshing_chords (Grob *me, else if (down_ball_type == 0 && up_ball_type == 2) shift_amount *= 0.75; } - + /* * Fix issue #44: * @@ -290,24 +305,24 @@ check_meshing_chords (Grob *me, { Grob *staff = Staff_symbol_referencer::get_staff_symbol (me); if (!Staff_symbol_referencer::on_line (staff, ups[0])) - /* - TODO: consider junking the else body. - */ - if (to_boolean (me->get_property ("prefer-dotted-right"))) - { + { + /* + TODO: consider junking the else body. + */ + if (to_boolean (me->get_property ("prefer-dotted-right"))) shift_amount = 0.5; - } - else - { - 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 + { + 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); + } + } } /* For full or close half collisions, the right hand head may - obscure dots. Move dots to the right. */ + obscure dots. Move dots to the right. */ if (abs (shift_amount) > 1e-6 && Rhythmic_head::dot_count (head_down) > Rhythmic_head::dot_count (head_up) && (full_collide || close_half_collide)) @@ -345,13 +360,13 @@ check_meshing_chords (Grob *me, } -MAKE_SCHEME_CALLBACK (Note_collision_interface, calc_positioning_done, 1) +MAKE_SCHEME_CALLBACK (Note_collision_interface, calc_positioning_done, 1) SCM Note_collision_interface::calc_positioning_done (SCM smob) { Grob *me = unsmob_grob (smob); me->set_property ("positioning-done", SCM_BOOL_T); - + Drul_array > clash_groups = get_clash_groups (me); Direction d = UP; @@ -361,7 +376,7 @@ Note_collision_interface::calc_positioning_done (SCM smob) { /* Trigger positioning - */ + */ clash_groups[d][i]->extent (me, X_AXIS); } } @@ -430,9 +445,7 @@ Note_collision_interface::get_clash_groups (Grob *me) if (Note_column::has_interface (se)) { if (!Note_column::dir (se)) - { - se->programming_error ("note-column has no direction"); - } + se->programming_error ("note-column has no direction"); else clash_groups[Note_column::dir (se)].push_back (se); } @@ -449,9 +462,9 @@ Note_collision_interface::get_clash_groups (Grob *me) return clash_groups; } -/** This complicated routine moves note columns around horizontally to - ensure that notes don't clash. - +/* + This complicated routine moves note columns around horizontally to + ensure that notes don't clash. */ SCM Note_collision_interface::automatic_shift (Grob *me, @@ -530,12 +543,12 @@ Note_collision_interface::automatic_shift (Grob *me, /* see input/regression/dot-up-voice-collision.ly - */ + */ for (vsize i = 0; i < clash_groups[UP].size (); i++) { Grob *g = clash_groups[UP][i]; Grob *dc = Note_column::dot_column (g); - + if (dc) for (vsize j = i + 1; j < clash_groups[UP].size (); j++) { @@ -543,7 +556,7 @@ Note_collision_interface::automatic_shift (Grob *me, Side_position_interface::add_support (dc, stem); } } - + /* Check if chords are meshing */ @@ -574,10 +587,8 @@ Note_collision_interface::forced_shift (Grob *me) SCM force = se->get_property ("force-hshift"); if (scm_is_number (force)) - { - tups = scm_cons (scm_cons (se->self_scm (), force), - tups); - } + tups = scm_cons (scm_cons (se->self_scm (), force), + tups); } return tups; }