X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fnote-spacing.cc;h=c4a79e403f7b18bb0313ce9a823ab481cf2cd8d3;hb=e3bd073b603167e110d3ecac4bfa3e1ca75e0106;hp=82640d4d626c9db8841537815756c68498fe9263;hpb=d3c50bb3e14b4ded57e6747ed5d122fabedebecb;p=lilypond.git diff --git a/lily/note-spacing.cc b/lily/note-spacing.cc index 82640d4d62..c4a79e403f 100644 --- a/lily/note-spacing.cc +++ b/lily/note-spacing.cc @@ -3,11 +3,13 @@ source file of the GNU LilyPond music typesetter - (c) 2001--2005 Han-Wen Nienhuys + (c) 2001--2007 Han-Wen Nienhuys */ #include "note-spacing.hh" +#include "directional-element-interface.hh" +#include "grob-array.hh" #include "paper-column.hh" #include "moment.hh" #include "note-column.hh" @@ -17,6 +19,7 @@ #include "staff-spacing.hh" #include "accidental-placement.hh" #include "output-def.hh" +#include "pointer-group-interface.hh" /* TODO: detect hshifts due to collisions, and account for them in @@ -27,9 +30,8 @@ void Note_spacing::get_spacing (Grob *me, Item *right_col, Real base_space, Real increment, Real *space, Real *fixed) { - - Drul_array props (me->get_property ("left-items"), - me->get_property ("right-items")); + Drul_array props (me->get_object ("left-items"), + me->get_object ("right-items")); Direction d = LEFT; Direction col_dir = right_col->break_status_dir (); Drul_array extents; @@ -37,14 +39,14 @@ Note_spacing::get_spacing (Grob *me, Item *right_col, Interval left_head_wid; do { - for (SCM s = props[d]; scm_is_pair (s); s = scm_cdr (s)) + vector const &items (ly_scm2link_array (props [d])); + for (vsize i = items.size (); i--;) { - Item *it = dynamic_cast (unsmob_grob (scm_car (s))); + Item *it = dynamic_cast (items[i]); if (d == RIGHT && it->break_status_dir () != col_dir) - { - it = it->find_prebroken_piece (col_dir); - } + it = it->find_prebroken_piece (col_dir); + /* some kind of mismatch, eg. a note column, that is behind a linebreak. @@ -62,9 +64,10 @@ Note_spacing::get_spacing (Grob *me, Item *right_col, continue; } - if (d == LEFT) + if (d == LEFT + && Note_column::has_interface (it)) { - SCM r = it->get_property ("rest"); + SCM r = it->get_object ("rest"); Grob *g = unsmob_grob (r); if (!g) g = Note_column::first_head (it); @@ -74,7 +77,12 @@ Note_spacing::get_spacing (Grob *me, Item *right_col, first note head will be. */ if (g) - left_head_wid = g->extent (it_col, X_AXIS); + { + if (g->common_refpoint (it_col, X_AXIS) != it_col) + programming_error ("Note_spacing::get_spacing(): Common refpoint incorrect"); + else + left_head_wid = g->extent (it_col, X_AXIS); + } } extents[d].unite (it->extent (it_col, X_AXIS)); @@ -91,6 +99,9 @@ Note_spacing::get_spacing (Grob *me, Item *right_col, extents[d].unite (v); } + + if (Grob *arpeggio = Note_column::arpeggio (it)) + extents[d].unite (arpeggio->extent (it_col, X_AXIS)); } } @@ -101,6 +112,7 @@ Note_spacing::get_spacing (Grob *me, Item *right_col, /* We look at the width of the note head, since smaller heads get less space + eg. a quarter rest gets almost 0.5 ss less horizontal space than a note. What is sticking out of the note head (eg. a flag), doesn't get @@ -121,9 +133,16 @@ Note_spacing::get_spacing (Grob *me, Item *right_col, (extents[LEFT][RIGHT] - left_head_wid[RIGHT]) / 2)) /* - What is sticking out of the right note: + What is sticking out on the left side of the right note: */ - + (extents[RIGHT].is_empty () ? 0.0 : - extents[RIGHT][LEFT] / 2); + + (extents[RIGHT].is_empty () + ? 0.0 + : ((- extents[RIGHT][LEFT] / 2) + + /* + Add that which sticks out a lot. + */ + + max (0.0, -extents[RIGHT][LEFT] - (base_space - 0.5 * increment)))); /* We don't do complicated stuff: (base_space - increment) is the @@ -133,9 +152,14 @@ Note_spacing::get_spacing (Grob *me, Item *right_col, */ *space = (base_space - increment) + *fixed; +#if 0 + /* + The below situation is now handled by the "sticks out a lot" case + above. However we keep around the code for a few releases before + we drop it. + */ if (!extents[RIGHT].is_empty () - && (Item::is_breakable (right_col) - || right_col->original_)) + && (Paper_column::is_breakable (right_col))) { /* This is for the situation @@ -150,7 +174,8 @@ Note_spacing::get_spacing (Grob *me, Item *right_col, *space += -extents[RIGHT][LEFT] / 2; *fixed += -extents[RIGHT][LEFT] / 2; } - +#endif + stem_dir_correction (me, right_col, increment, space, fixed); } @@ -176,15 +201,15 @@ Note_spacing::right_column (Grob *me) if (!me->is_live ()) return 0; - SCM right = me->get_property ("right-items"); + Grob_array *a = unsmob_grob_array (me->get_object ("right-items")); Item *mincol = 0; int min_rank = INT_MAX; bool prune = false; - for (SCM s = right; scm_is_pair (s); s = scm_cdr (s)) + for (vsize i = 0; a && i < a->size (); i++) { - Item *ri = unsmob_item (scm_car (s)); - + Item *ri = a->item (i); Item *col = ri->get_column (); + int rank = Paper_column::get_rank (col); if (rank < min_rank) @@ -197,28 +222,18 @@ Note_spacing::right_column (Grob *me) } } - if (prune) + if (prune && a) { - // I'm a lazy bum. We could do this in-place. - SCM newright = SCM_EOL; - for (SCM s = right; scm_is_pair (s); s = scm_cdr (s)) + vector &right = a->array_reference (); + for (vsize i = right.size (); i--;) { - if (unsmob_item (scm_car (s))->get_column () == mincol) - newright = scm_cons (scm_car (s), newright); + if (dynamic_cast (right[i])->get_column () != mincol) + right.erase (right.begin () + i); } - - me->set_property ("right-items", newright); } if (!mincol) - { - /* - int r = Paper_column::get_rank (dynamic_cast(me)->get_column ()); - programming_error (_f ("Spacing wish column %d has no right item.", r)); - */ - - return 0; - } + return 0; return mincol; } @@ -238,8 +253,8 @@ Note_spacing::stem_dir_correction (Grob *me, Item *rcolumn, Drul_array stem_dirs (CENTER, CENTER); Drul_array stem_posns; Drul_array head_posns; - Drul_array props (me->get_property ("left-items"), - me->get_property ("right-items")); + Drul_array props (me->get_object ("left-items"), + me->get_object ("right-items")); Drul_array beams_drul (0, 0); Drul_array stems_drul (0, 0); @@ -255,9 +270,10 @@ Note_spacing::stem_dir_correction (Grob *me, Item *rcolumn, do { - for (SCM s = props[d]; scm_is_pair (s); s = scm_cdr (s)) + vector const &items (ly_scm2link_array (props [d])); + for (vsize i = 0; i < items.size (); i++) { - Item *it = dynamic_cast (unsmob_grob (scm_car (s))); + Item *it = dynamic_cast (items[i]); if (d == RIGHT) acc_right = acc_right || Note_column::accidentals (it); @@ -269,9 +285,7 @@ Note_spacing::stem_dir_correction (Grob *me, Item *rcolumn, if (d == RIGHT && Separation_item::has_interface (it)) { if (it->get_column () != rcolumn) - { - it = it->find_prebroken_piece (rcolumn->break_status_dir ()); - } + it = it->find_prebroken_piece (rcolumn->break_status_dir ()); Grob *last = Separation_item::extremal_break_aligned_grob (it, LEFT, &bar_xextent); @@ -293,13 +307,13 @@ Note_spacing::stem_dir_correction (Grob *me, Item *rcolumn, stems_drul[d] = stem; beams_drul[d] = Stem::get_beam (stem); - Direction sd = Stem::get_direction (stem); - if (stem_dirs[d] && stem_dirs[d] != sd) + Direction stem_dir = get_grob_direction (stem); + if (stem_dirs[d] && stem_dirs[d] != stem_dir) { correct_stem_dirs = false; continue; } - stem_dirs[d] = sd; + stem_dirs[d] = stem_dir; /* Correction doesn't seem appropriate when there is a large flag @@ -307,17 +321,23 @@ Note_spacing::stem_dir_correction (Grob *me, Item *rcolumn, */ if (d == LEFT && Stem::duration_log (stem) > 2 && !Stem::get_beam (stem)) - { - correct_stem_dirs = false; - } + correct_stem_dirs = false; Interval hp = Stem::head_positions (stem); - if (!hp.is_empty ()) + if (correct_stem_dirs + && !hp.is_empty ()) { - Real chord_start = hp[sd]; - Real stem_end = Stem::stem_end_position (stem); + Real chord_start = hp[stem_dir]; - stem_posns[d] = Interval (min (chord_start, stem_end), max (chord_start, stem_end)); + /* + 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); } } @@ -336,6 +356,7 @@ Note_spacing::stem_dir_correction (Grob *me, Item *rcolumn, { stem_dirs[RIGHT] = -stem_dirs[LEFT]; stem_posns[RIGHT] = bar_yextent; + stem_posns[RIGHT] *= 2; } if (correct_stem_dirs && stem_dirs[LEFT] * stem_dirs[RIGHT] == -1) @@ -390,9 +411,7 @@ Note_spacing::stem_dir_correction (Grob *me, Item *rcolumn, } if (!bar_yextent.is_empty ()) - { - correction *= 0.5; - } + correction *= 0.5; } } else if (correct_stem_dirs && stem_dirs[LEFT] * stem_dirs[RIGHT] == UP) @@ -426,7 +445,7 @@ Note_spacing::stem_dir_correction (Grob *me, Item *rcolumn, Real delta = head_posns[-lowest][DOWN] - head_posns[lowest][UP]; Real corr = robust_scm2double (me->get_property ("same-direction-correction"), 0); - + if (delta > 1) correction = -lowest * corr; } @@ -438,7 +457,15 @@ Note_spacing::stem_dir_correction (Grob *me, Item *rcolumn, */ } -ADD_INTERFACE (Note_spacing, "note-spacing-interface", +ADD_INTERFACE (Note_spacing, "This object calculates spacing wishes for individual voices.", - "left-items right-items stem-spacing-correction same-direction-correction knee-spacing-correction"); + + + "knee-spacing-correction " + "left-items " + "right-items " + "same-direction-correction " + "stem-spacing-correction " + + );