From e04d2f37f505bd6de6ae8b3923de9b68a3a64455 Mon Sep 17 00:00:00 2001 From: Joe Neeman Date: Sun, 2 Aug 2009 13:18:32 -0700 Subject: [PATCH] Simplify the handling of neighbor columns. Now we keep track of only one left-neighbor and one right-neighbor for each column. This makes the loose column determination simpler and less fragile. Also, we now use a spacing wish if it has any right-item in the appropriate column (before, we only used it if its left-most right-item was in the appropriate column). This fixes the ad-hoc loose-column determination for strict note spacing. --- lily/note-spacing.cc | 2 + lily/spaceable-grob.cc | 4 +- lily/spacing-determine-loose-columns.cc | 134 +++++------------------- lily/spacing-interface.cc | 39 +------ lily/spacing-spanner.cc | 28 +++-- scm/define-grob-properties.scm | 9 +- 6 files changed, 56 insertions(+), 160 deletions(-) diff --git a/lily/note-spacing.cc b/lily/note-spacing.cc index bd796a7135..81cb8c2fcd 100644 --- a/lily/note-spacing.cc +++ b/lily/note-spacing.cc @@ -235,6 +235,8 @@ Note_spacing::stem_dir_correction (Grob *me, Item *rcolumn, 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. diff --git a/lily/spaceable-grob.cc b/lily/spaceable-grob.cc index 0412edcf02..d736c25420 100644 --- a/lily/spaceable-grob.cc +++ b/lily/spaceable-grob.cc @@ -95,10 +95,10 @@ ADD_INTERFACE (Spaceable_grob, "allow-loose-spacing " "ideal-distances " "keep-inside-line " - "left-neighbors " + "left-neighbor " "measure-length " "minimum-distances " - "right-neighbors " + "right-neighbor " "spacing-wishes " ); diff --git a/lily/spacing-determine-loose-columns.cc b/lily/spacing-determine-loose-columns.cc index 20771542fb..7aa42caece 100644 --- a/lily/spacing-determine-loose-columns.cc +++ b/lily/spacing-determine-loose-columns.cc @@ -73,28 +73,15 @@ is_loose_column (Grob *l, Grob *col, Grob *r, Spacing_options const *options) */ - extract_grob_set (col, "right-neighbors", rns); - extract_grob_set (col, "left-neighbors", lns); - - if (lns.empty () || rns.empty ()) - return false; - - - Item *l_neighbor = dynamic_cast (lns[0]); - Item *r_neighbor = dynamic_cast (rns[0]); + Item *r_neighbor = unsmob_item (col->get_object ("right-neighbor")); + Item *l_neighbor = unsmob_item (col->get_object ("left-neighbor")); if (!l_neighbor || !r_neighbor) return false; - l_neighbor = l_neighbor->get_column (); - r_neighbor = dynamic_cast (Spacing_interface::right_column (r_neighbor)); - if (l == l_neighbor && r == r_neighbor) return false; - if (!l_neighbor || !r_neighbor) - return false; - /* Only declare loose if the bounds make a little sense. This means some cases (two isolated, consecutive clef changes) won't be @@ -200,19 +187,14 @@ Spacing_spanner::prune_loose_columns (Grob *me, if (loose) { - extract_grob_set (c, "right-neighbors", rns_arr); - extract_grob_set (c, "left-neighbors", lns_arr); - - SCM lns = lns_arr.size () ? lns_arr.back ()->self_scm () : SCM_BOOL_F; - SCM rns = rns_arr.size () ? rns_arr.back ()->self_scm () : SCM_BOOL_F; + Grob *right_neighbor = unsmob_grob (c->get_object ("right-neighbor")); + Grob *left_neighbor = unsmob_grob (c->get_object ("left-neighbor")); /* Either object can be non existent, if the score ends prematurely. */ - - extract_grob_set (unsmob_grob (rns), "right-items", right_items); - if (right_items.size () == 0 || !unsmob_grob (lns)) + if (!right_neighbor || !left_neighbor) { c->programming_error ("Cannot determine neighbors for floating column. "); c->set_object ("between-cols", scm_cons (cols->at (i-1)->self_scm (), @@ -220,20 +202,9 @@ Spacing_spanner::prune_loose_columns (Grob *me, } else { - Grob *min_item = 0; - int min_rank = INT_MAX; - for (vsize j = 0; j < right_items.size (); j ++) - { - int rank = dynamic_cast (right_items[j])->get_column ()->get_rank (); - if (rank < min_rank) - { - min_item = right_items[j]; - min_rank = rank; - } - } - - c->set_object ("between-cols", scm_cons (lns, - min_item->self_scm ())); + c->set_object ("between-cols", scm_cons (left_neighbor->self_scm (), + right_neighbor->self_scm ())); + /* Set distance constraints for loose columns @@ -260,72 +231,38 @@ Spacing_spanner::set_explicit_neighbor_columns (vector const &cols) { for (vsize i = 0; i < cols.size (); i++) { - SCM right_neighbors = Grob_array::make_array (); - Grob_array *rn_arr = unsmob_grob_array (right_neighbors); - int min_rank = INT_MAX; - extract_grob_set (cols[i], "spacing-wishes", wishes); - for (vsize k = wishes.size (); k--;) + for (vsize j = wishes.size (); j--;) { - Item *wish = dynamic_cast (wishes[k]); - - Item *lc = wish->get_column (); - Grob *right = Spacing_interface::right_column (wish); - - if (!right) - continue; - - Item *rc = dynamic_cast (right); + Item *wish = dynamic_cast (wishes[j]); + Item *left_col = wish->get_column (); + int left_rank = Paper_column::get_rank (left_col); + int min_right_rank = INT_MAX; - int right_rank = Paper_column::get_rank (rc); - int left_rank = Paper_column::get_rank (lc); - - /* - update the left column. - */ - if (right_rank <= min_rank) - { - if (right_rank < min_rank) - rn_arr->clear (); - - min_rank = right_rank; - rn_arr->add (wish); - } - - /* - update the right column of the wish. - */ - int maxrank = 0; - - extract_grob_set (rc, "left-neighbors", lns_arr); - if (lns_arr.size ()) + extract_grob_set (wish, "right-items", right_items); + for (vsize k = right_items.size (); k--;) { - Item *it = dynamic_cast (lns_arr.back ()); - maxrank = Paper_column::get_rank (it->get_column ()); - } + Item *right_col = dynamic_cast (right_items[k])->get_column (); + int right_rank = Paper_column::get_rank (right_col); - if (left_rank >= maxrank) - { - - if (left_rank > maxrank) + if (right_rank < min_right_rank) { - Grob_array *ga = unsmob_grob_array (rc->get_object ("left-neighbors")); - if (ga) - ga->clear (); + left_col->set_object ("right-neighbor", right_col->self_scm ()); + min_right_rank = right_rank; } - Pointer_group_interface::add_grob (rc, ly_symbol2scm ("left-neighbors"), wish); + Grob *old_left_neighbor = unsmob_grob (right_col->get_object ("left-neighbor")); + if (!old_left_neighbor || left_rank > Paper_column::get_rank (old_left_neighbor)) + right_col->set_object ("left-neighbor", left_col->self_scm ()); } } - - if (rn_arr->size ()) - cols[i]->set_object ("right-neighbors", right_neighbors); } } /* Set neighboring columns that have no left/right-neighbor set yet. Only do breakable non-musical columns, and musical columns. + Why only these? --jneem */ void Spacing_spanner::set_implicit_neighbor_columns (vector const &cols) @@ -336,24 +273,9 @@ Spacing_spanner::set_implicit_neighbor_columns (vector const &cols) if (!Paper_column::is_breakable (it) && !Paper_column::is_musical (it)) continue; - /* - sloppy with typing left/right-neighbors should take list, but paper-column found instead. - */ - extract_grob_set (cols[i], "left-neighbors", lns); - if (lns.empty () && i) - { - SCM ga_scm = Grob_array::make_array (); - Grob_array *ga = unsmob_grob_array (ga_scm); - ga->add (cols[i - 1]); - cols[i]->set_object ("left-neighbors", ga_scm); - } - extract_grob_set (cols[i], "right-neighbors", rns); - if (rns.empty () && i + 1 < cols.size ()) - { - SCM ga_scm = Grob_array::make_array (); - Grob_array *ga = unsmob_grob_array (ga_scm); - ga->add (cols[i + 1]); - cols[i]->set_object ("right-neighbors", ga_scm); - } + if (i && !unsmob_grob (cols[i]->get_object ("left-neighbor"))) + cols[i]->set_object ("left-neighbor", cols[i-1]->self_scm ()); + if (i + 1 < cols.size () && !unsmob_grob (cols[i]->get_object ("right-neighbor"))) + cols[i]->set_object ("right-neighbor", cols[i+1]->self_scm ()); } } diff --git a/lily/spacing-interface.cc b/lily/spacing-interface.cc index f7d6b8d31f..6e8027bc8c 100644 --- a/lily/spacing-interface.cc +++ b/lily/spacing-interface.cc @@ -92,20 +92,7 @@ Spacing_interface::minimum_distance (Grob *me, Grob *right) } /* - Compute the column of the right-items. This is a big function, - since RIGHT-ITEMS may span more columns (eg. if a clef is inserted, - this will add a new column to RIGHT-ITEMS. Here we look at the - columns, and return the left-most. If there are multiple columns, we - prune RIGHT-ITEMS. - - If we end up pruning, we add a left-neighbor to every column that - gets pruned. This ensures that loose columns in cross-staff music - do indeed get marked as loose. The problem situation is when a voice - passes from staff 1 to staff 2 and a clef appears later on in staff 1. - Then the NoteSpacing attached to the last note in staff 1 has two - right-items: one pointing to the next note in staff 2 and one pointing - to the clef. We will prune the clef right-item here and, unless we add - a left-neighbor to the clef, it won't get marked as loose. + Compute the left-most column of the right-items. */ Item * Spacing_interface::right_column (Grob *me) @@ -116,7 +103,6 @@ Spacing_interface::right_column (Grob *me) Grob_array *a = unsmob_grob_array (me->get_object ("right-items")); Item *mincol = 0; int min_rank = INT_MAX; - bool prune = false; for (vsize i = 0; a && i < a->size (); i++) { Item *ri = a->item (i); @@ -127,31 +113,8 @@ Spacing_interface::right_column (Grob *me) if (rank < min_rank) { min_rank = rank; - if (mincol) - prune = true; - mincol = col; } - else if (rank > min_rank) - prune = true; - } - - if (prune && a) - { - vector &right = a->array_reference (); - for (vsize i = right.size (); i--;) - { - if (dynamic_cast (right[i])->get_column () != mincol) - { - extract_grob_set (right[i], "left-neighbors", lns); - if (lns.empty ()) - Pointer_group_interface::add_grob (right[i], - ly_symbol2scm ("left-neighbors"), - dynamic_cast (me)->get_column ()); - - right.erase (right.begin () + i); - } - } } return mincol; diff --git a/lily/spacing-spanner.cc b/lily/spacing-spanner.cc index 99fe9824a8..274905faf5 100644 --- a/lily/spacing-spanner.cc +++ b/lily/spacing-spanner.cc @@ -324,21 +324,33 @@ Spacing_spanner::musical_column_spacing (Grob *me, else { vector springs; - extract_grob_set (left_col, "right-neighbors", neighbors); + extract_grob_set (left_col, "spacing-wishes", wishes); - for (vsize i = 0; i < neighbors.size (); i++) + for (vsize i = 0; i < wishes.size (); i++) { - Grob *wish = neighbors[i]; + Grob *wish = wishes[i]; + if (Spacing_interface::left_column (wish) != left_col) + { + /* This shouldn't really happen, but the ancient music + stuff really messes up the spacing code, grrr + */ + continue; + } - Item *wish_rcol = Spacing_interface::right_column (wish); - if (Spacing_interface::left_column (wish) != left_col - || (wish_rcol != right_col && wish_rcol != right_col->original ())) - continue; + extract_grob_set (wish, "right-items", right_items); + bool found_matching_column = false; + for (vsize j = 0; j < right_items.size (); j++) + { + Item *it = dynamic_cast (right_items[j]); + if (it && (right_col == it->get_column () + || right_col->original () == it->get_column ())) + found_matching_column = true; + } /* This is probably a waste of time in the case of polyphonic music. */ - if (Note_spacing::has_interface (wish)) + if (found_matching_column && Note_spacing::has_interface (wish)) { Real inc = options->increment_; Grob *gsp = unsmob_grob (left_col->get_object ("grace-spacing")); diff --git a/scm/define-grob-properties.scm b/scm/define-grob-properties.scm index 98eb2c022c..ac09201044 100644 --- a/scm/define-grob-properties.scm +++ b/scm/define-grob-properties.scm @@ -926,11 +926,8 @@ in addition to notes and stems.") empty in a particular staff, then that staff is erased.") (left-items ,ly:grob-array? "DOCME") - (left-neighbors ,ly:grob-array? "An array of @code{spacing-wishes} grobs -that are close to the current column. - -The closest @code{spacing-wishes} determine the actual distances between the -columns.") + (left-neighbor ,ly:grob? "The right-most column that has a spacing-wish +for this column.") (normal-stems ,ly:grob-array? "An array of visible stems.") (note-columns ,ly:grob-array? "An array of @code{NoteColumn} grobs.") @@ -949,7 +946,7 @@ relevant for finding the @code{pure-Y-extent}.") (rest-collision ,ly:grob? "A rest collision that a rest is in.") (rests ,ly:grob-array? "An array of rest objects.") (right-items ,ly:grob-array? "DOCME") - (right-neighbors ,ly:grob-array? "See @code{left-neighbors}.") + (right-neighbor ,ly:grob? "See @code{left-neighbor}.") (separation-item ,ly:grob? "A pointer to a @code{SeparationItem} object.") -- 2.39.2