X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fnote-spacing.cc;h=7964a2966e0885e25739209655da14047de8df80;hb=d765f3af45be51f15da55cf570a4b172200e1035;hp=88beea31424e3faca43faa94cf4fd9b2ea50417c;hpb=ce521e79fd7669b45c8c1132e4b5693a03b5d90a;p=lilypond.git diff --git a/lily/note-spacing.cc b/lily/note-spacing.cc index 88beea3142..7964a2966e 100644 --- a/lily/note-spacing.cc +++ b/lily/note-spacing.cc @@ -17,27 +17,64 @@ #include "stem.hh" #include "separation-item.hh" #include "staff-spacing.hh" +#include "accidental-placement.hh" -bool -Note_spacing::has_interface (Grob* g) +void +Note_spacing::get_spacing (Grob *me, Item* right_col, + Real base_space, Real increment, Real *space, Real *fixed) { - return g && g->has_interface (ly_symbol2scm ("note-spacing-interface")); -} -Real -Note_spacing::get_spacing (Grob *me) -{ Drul_array props(me->get_grob_property ("left-items"), me->get_grob_property ("right-items")); Direction d = LEFT; + Direction col_dir = right_col->break_status_dir (); Drul_array extents; + + Interval left_head_wid; do { for (SCM s = props[d]; gh_pair_p (s); s = gh_cdr (s)) { Item * it= dynamic_cast (unsmob_grob (gh_car(s))); - extents[d].unite (it->extent (it->column_l (), X_AXIS)); + + if (d == RIGHT && it->break_status_dir () != col_dir) + { + it = it -> find_prebroken_piece (col_dir); + + } + /* + some kind of mismatch, eg. a note column, that is behind a + linebreak. + */ + if (!it) + continue; + + Item *it_col = it->get_column (); + if (d == RIGHT && right_col != it_col) + continue; + + if (Separation_item::has_interface (it)) + { + extents[d].unite (Separation_item::width (it)); + continue; + } + if (d == LEFT) + { + SCM r = it->get_grob_property ("rest"); + Grob * g = unsmob_grob (r); + if (!g) + g = Note_column::first_head (it); + + /* + Ugh. If Stem is switched off, we don't know what the + first note head will be. + */ + if (g) + left_head_wid = g->extent(it_col, X_AXIS); + } + + extents[d].unite (it->extent (it_col, X_AXIS)); if (d == RIGHT) { Grob * accs = Note_column::accidentals (it); @@ -45,7 +82,12 @@ Note_spacing::get_spacing (Grob *me) accs = Note_column::accidentals (it->get_parent (X_AXIS)); if (accs) - extents[d].unite (accs->extent (it->column_l (), X_AXIS)); + { + Interval v = + Accidental_placement::get_relevant_accidental_extent (accs, it_col, me); + + extents[d].unite (v); + } } } @@ -54,23 +96,43 @@ Note_spacing::get_spacing (Grob *me) } while (flip (&d) != LEFT); + /* - - What's sticking out at the left of the right side has less - influence. + 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 + the full amount of space. */ - Real dx= extents[LEFT][RIGHT] - 0.5 * extents[RIGHT][LEFT]; - return dx; + *fixed = left_head_wid.empty_b () ? increment : left_head_wid[RIGHT]; + *space = (base_space - increment) + *fixed + + (extents[LEFT][RIGHT] + - (left_head_wid.empty_b () ? 0.0 : left_head_wid[RIGHT]))/ 2; + ; + + if (*space - *fixed < 2 * ((- extents[RIGHT][LEFT]) >? 0)) + { + /* + + What's sticking out at the left of the right side has less + influence. We only take it into account if there is not enough + space. + + this sucks: this criterion is discontinuous; FIXME. + */ + *space += 0.5 * (( -extents[RIGHT][LEFT]) >? 0); + } + + stem_dir_correction (me, right_col, increment, space, fixed); } Item * Note_spacing::left_column (Grob *me) { - if (me->immutable_property_alist_ == SCM_EOL) + if (!me->live()) return 0; - return dynamic_cast (me)->column_l (); + return dynamic_cast (me)->get_column (); } /* @@ -84,10 +146,7 @@ prune RIGHT-ITEMS. Item * Note_spacing::right_column (Grob*me) { - /* - ugh. should have generic is_live() method? - */ - if (me->immutable_property_alist_ == SCM_EOL) + if (!me->live()) return 0; SCM right = me->get_grob_property ("right-items"); @@ -98,8 +157,8 @@ Note_spacing::right_column (Grob*me) { Item * ri = unsmob_item (gh_car (s)); - Item * col = ri->column_l (); - int rank = Paper_column::rank_i (col); + Item * col = ri->get_column (); + int rank = Paper_column::get_rank (col); if (rank < min_rank) { @@ -117,7 +176,7 @@ Note_spacing::right_column (Grob*me) SCM newright = SCM_EOL; for (SCM s = right ; gh_pair_p (s) ; s =gh_cdr (s)) { - if (unsmob_item (gh_car (s))->column_l () == mincol) + if (unsmob_item (gh_car (s))->get_column () == mincol) newright = gh_cons (gh_car (s), newright); } @@ -127,7 +186,7 @@ Note_spacing::right_column (Grob*me) if (!mincol) { /* - int r = Paper_column::rank_i (dynamic_cast(me)->column_l ()); + int r = Paper_column::get_rank (dynamic_cast(me)->get_column ()); programming_error (_f("Spacing wish column %d has no right item.", r)); */ @@ -144,12 +203,11 @@ Note_spacing::right_column (Grob*me) TODO: have to check wether the stems are in the same staff. - TODO: also correct for bar lines in RIGHT-ITEMS. Should check if - the barline is the leftmost object of the break alignment. - */ -Real -Note_spacing::stem_dir_correction (Grob*me) +void +Note_spacing::stem_dir_correction (Grob*me, Item * rcolumn, + Real increment, + Real * space, Real *fixed) { Drul_array stem_dirs(CENTER,CENTER); Drul_array stem_posns; @@ -157,6 +215,7 @@ Note_spacing::stem_dir_correction (Grob*me) Drul_array props(me->get_grob_property ("left-items"), me->get_grob_property ("right-items")); + Drul_array beams_drul(0,0); Real correction = 0.0; stem_dirs[LEFT] = stem_dirs[RIGHT] = CENTER; @@ -177,12 +236,17 @@ Note_spacing::stem_dir_correction (Grob*me) if (d == RIGHT) acc_right = acc_right || Note_column::accidentals (it); - Grob *stem = Note_column::stem_l (it); + Grob *stem = Note_column::get_stem (it); - if (!stem) + if (!stem || !stem->live ()) { if (d == RIGHT && Separation_item::has_interface (it)) { + if (it->get_column () != rcolumn) + { + it = it->find_prebroken_piece (rcolumn->break_status_dir ()); + } + Grob *last = Staff_spacing::extremal_break_aligned_grob (it, LEFT, &bar_xextent); if (last) @@ -191,22 +255,37 @@ Note_spacing::stem_dir_correction (Grob*me) break; } - goto exit_func; + return ; } + if(Stem::invisible_b (stem)) { - correct = false; - goto exit_func ; + return ; } + beams_drul[d] = Stem::get_beam (stem); + + Direction sd = Stem::get_direction (stem); if (stem_dirs[d] && stem_dirs[d] != sd) { - correct = false; - goto exit_func; + return ; } stem_dirs[d] = sd; + /* + 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); Real chord_start = hp[sd]; Real stem_end = Stem::stem_end_position (stem); @@ -223,7 +302,7 @@ Note_spacing::stem_dir_correction (Grob*me) */ if (acc_right) - return 0.0; + return ; if (!bar_yextent.empty_b()) { @@ -233,27 +312,42 @@ Note_spacing::stem_dir_correction (Grob*me) if (correct &&stem_dirs[LEFT] *stem_dirs[RIGHT] == -1) { - - intersect = stem_posns[LEFT]; - intersect.intersect(stem_posns[RIGHT]); - correct = correct && !intersect.empty_b (); + if (beams_drul[LEFT] && beams_drul[LEFT] == beams_drul[RIGHT]) + { + /* + this is a knee: maximal correction. + */ + + correction = increment* stem_dirs[LEFT]; + correction *= gh_scm2double (me->get_grob_property ("knee-spacing-correction")); + *fixed += correction; + } + else + { + intersect = stem_posns[LEFT]; + intersect.intersect(stem_posns[RIGHT]); + correct = correct && !intersect.empty_b (); - if (!correct) - return 0.0; - /* - Ugh. 7 is hardcoded. - */ - correction = abs (intersect.length ()); - correction = (correction/7) get_grob_property ("stem-spacing-correction")); + if (!correct) + return; + + correction = abs (intersect.length ()); - if (!bar_yextent.empty_b()) - { - correction *= 0.5; + + /* + Ugh. 7 is hardcoded. + */ + correction = (correction/7) get_grob_property ("stem-spacing-correction")); + + if (!bar_yextent.empty_b()) + { + correction *= 0.5; + } } } - else if (correct) + else if (correct && stem_dirs[LEFT] *stem_dirs[RIGHT] == UP) { /* Correct for the following situation: @@ -278,7 +372,7 @@ Note_spacing::stem_dir_correction (Grob*me) Interval hp = head_posns[LEFT]; hp.intersect (head_posns[RIGHT]); if (!hp.empty_b()) - return 0.0; + return ; Direction lowest = (head_posns[LEFT][DOWN] > head_posns[RIGHT][UP]) ? RIGHT : LEFT; @@ -292,8 +386,14 @@ Note_spacing::stem_dir_correction (Grob*me) if (!bar_xextent.empty_b()) correction += - bar_xextent[LEFT]; - - exit_func: - return correction; + + *space += correction; } + + + +ADD_INTERFACE (Note_spacing,"note-spacing-interface", + "", + "left-items right-items stem-spacing-correction knee-spacing-correction"); +