X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fbreak-substitution.cc;h=d198753d673b88bda66d51e8029259f9d4307681;hb=b872748c6aa8bb721ced458691b38ac2fac5dfc8;hp=764186ee3f07e003ff0e78a2ad249fd13842c8d9;hpb=75eebcb49e52d296b1da3e1074e0825d2c780db4;p=lilypond.git diff --git a/lily/break-substitution.cc b/lily/break-substitution.cc index 764186ee3f..d198753d67 100644 --- a/lily/break-substitution.cc +++ b/lily/break-substitution.cc @@ -1,18 +1,29 @@ /* - break-substitution.cc -- implement grob break substitution. + This file is part of LilyPond, the GNU music typesetter. - source file of the GNU LilyPond music typesetter + Copyright (C) 2001--2015 Han-Wen Nienhuys - (c) 2001--2006 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 #include using namespace std; -#include "grob-array.hh" #include "item.hh" #include "system.hh" +#include "grob-array.hh" static SCM break_criterion; void @@ -32,39 +43,39 @@ substitute_grob (Grob *sc) Item *i = dynamic_cast (sc); Direction d = to_dir (break_criterion); if (i && i->break_status_dir () != d) - { - Item *br = i->find_prebroken_piece (d); - return br; - } + { + Item *br = i->find_prebroken_piece (d); + return br; + } } else { System *line - = dynamic_cast (unsmob_grob (break_criterion)); + = unsmob (break_criterion); if (sc->get_system () != line) - sc = sc->find_broken_piece (line); + sc = sc->find_broken_piece (line); /* now: !sc || (sc && sc->get_system () == line) */ if (!sc) - return 0; + return 0; /* now: sc && sc->get_system () == line */ if (!line) - return sc; + return sc; /* - We don't return SCM_UNDEFINED for - suicided grobs, for two reasons + We don't return SCM_UNDEFINED for + suicided grobs, for two reasons - - it doesn't work (strange disappearing objects) + - it doesn't work (strange disappearing objects) - - it forces us to mark the parents of a grob, leading to - a huge recursion in the GC routine. + - it forces us to mark the parents of a grob, leading to + a huge recursion in the GC routine. */ if (sc->common_refpoint (line, X_AXIS) - && sc->common_refpoint (line, Y_AXIS)) - return sc; + && sc->common_refpoint (line, Y_AXIS)) + return sc; return 0; } @@ -88,11 +99,11 @@ substitute_grob (Grob *sc) SCM do_break_substitution (SCM src) { - again: +again: - if (unsmob_grob (src)) + if (unsmob (src)) { - Grob *new_ptr = substitute_grob (unsmob_grob (src)); + Grob *new_ptr = substitute_grob (unsmob (src)); return new_ptr ? new_ptr->self_scm () : SCM_UNDEFINED; } else if (scm_is_vector (src)) @@ -100,33 +111,33 @@ do_break_substitution (SCM src) int len = scm_c_vector_length (src); SCM nv = scm_c_make_vector (len, SCM_UNDEFINED); for (int i = 0; i < len; i++) - { - SCM si = scm_from_int (i); - scm_vector_set_x (nv, si, - do_break_substitution (scm_vector_ref (src, si))); - } + { + SCM si = scm_from_int (i); + scm_vector_set_x (nv, si, + do_break_substitution (scm_vector_ref (src, si))); + } } else if (scm_is_pair (src)) { /* - UGH! breaks on circular lists. + UGH! breaks on circular lists. */ SCM newcar = do_break_substitution (scm_car (src)); SCM oldcdr = scm_cdr (src); - if (newcar == SCM_UNDEFINED - && (scm_is_pair (oldcdr) || oldcdr == SCM_EOL)) - { - /* - This is tail-recursion, ie. + if (SCM_UNBNDP (newcar) + && (scm_is_pair (oldcdr) || scm_is_null (oldcdr))) + { + /* + This is tail-recursion, ie. - return do_break_substution (cdr); + return do_break_substution (cdr); - We don't want to rely on the compiler to do this. Without - tail-recursion, this easily crashes with a stack overflow. */ - src = oldcdr; - goto again; - } + We don't want to rely on the compiler to do this. Without + tail-recursion, this easily crashes with a stack overflow. */ + src = oldcdr; + goto again; + } return scm_cons (newcar, do_break_substitution (oldcdr)); } @@ -136,34 +147,6 @@ do_break_substitution (SCM src) return src; } -/* - Perform substitution on GROB_LIST using a constant amount of stack. -*/ -Link_array temporary_substition_array; -void -substitute_grob_array (Grob_array *grob_arr, Grob_array *new_arr) -{ - Link_array &old_grobs (grob_arr->array_reference ()); - Link_array *new_grobs (new_arr == grob_arr - ? & temporary_substition_array - : &new_arr->array_reference ()); - - new_grobs->set_size (old_grobs.size ()); - Grob **array = (Grob **) new_grobs->accesses (); - Grob **ptr = array; - for (int i = 0; i < old_grobs.size (); i++) - { - Grob *orig = old_grobs[i]; - Grob *new_grob = substitute_grob (orig); - if (new_grob) - *ptr++ = new_grob; - } - - new_grobs->set_size (ptr - array); - if (new_arr == grob_arr) - new_arr->set_array (*new_grobs); -} - /* We don't do @@ -224,8 +207,8 @@ spanner_system_range (Spanner *sp) else { if (sp->broken_intos_.size ()) - rv = Slice (sp->broken_intos_[0]->get_system ()->get_rank (), - sp->broken_intos_.top ()->get_system ()->get_rank ()); + rv = Slice (sp->broken_intos_[0]->get_system ()->get_rank (), + sp->broken_intos_.back ()->get_system ()->get_rank ()); } return rv; } @@ -237,14 +220,12 @@ item_system_range (Item *it) return Slice (st->get_rank (), st->get_rank ()); Slice sr; - Direction d = LEFT; - do + for (LEFT_and_RIGHT (d)) { Item *bi = it->find_prebroken_piece (d); if (bi && bi->get_system ()) - sr.add_point (bi->get_system ()->get_rank ()); + sr.add_point (bi->get_system ()->get_rank ()); } - while (flip (&d) != LEFT); return sr; } @@ -263,6 +244,8 @@ grob_system_range (Grob *g) struct Substitution_entry { Grob *grob_; + + /* Assumption: we have less than 32k paper columns. */ short left_; short right_; @@ -274,16 +257,16 @@ struct Substitution_entry */ if (sr.is_empty ()) { - /* - overflow if we don't treat this specially. - */ - left_ = 1; - right_ = -1; + /* + overflow if we don't treat this specially. + */ + left_ = 1; + right_ = -1; } else { - left_ = sr[LEFT]; - right_ = sr[RIGHT]; + left_ = (short) sr[LEFT]; + right_ = (short) sr[RIGHT]; } } Substitution_entry () @@ -297,20 +280,20 @@ struct Substitution_entry item_compare (void const *a, void const *b) { return ((Substitution_entry *)a)->left_ - - ((Substitution_entry *)b)->left_; + - ((Substitution_entry *)b)->left_; } static int spanner_compare (void const *a, void const *b) { return ((Substitution_entry *)a)->length () - - ((Substitution_entry *)b)->length (); + - ((Substitution_entry *)b)->length (); } }; bool Spanner::fast_substitute_grob_array (SCM sym, - Grob_array *grob_array) + Grob_array *grob_array) { int len = grob_array->size (); @@ -322,6 +305,8 @@ Spanner::fast_substitute_grob_array (SCM sym, /* We store items on the left, spanners on the right in this vector. + + FIXME: will not multithread. */ static Substitution_entry *vec; static int vec_room; @@ -337,7 +322,7 @@ Spanner::fast_substitute_grob_array (SCM sym, int spanner_index = len; int item_index = 0; - for (int i = 0; i < grob_array->size (); i++) + for (vsize i = 0; i < grob_array->size (); i++) { Grob *g = grob_array->grob (i); @@ -346,33 +331,34 @@ Spanner::fast_substitute_grob_array (SCM sym, int idx = 0; if (dynamic_cast (g)) - idx = --spanner_index; + idx = --spanner_index; else if (dynamic_cast (g)) - idx = item_index++; + idx = item_index++; vec[idx].set (g, sr); } qsort (vec, item_index, - sizeof (Substitution_entry), &Substitution_entry::item_compare); + sizeof (Substitution_entry), &Substitution_entry::item_compare); - Array item_indices; - Array spanner_indices; + vector item_indices; + vector spanner_indices; for (int i = 0; i <= system_range.length (); i++) { - item_indices.push (Slice (len, 0)); - spanner_indices.push (Slice (len, 0)); + item_indices.push_back (Slice (len, 0)); + spanner_indices.push_back (Slice (len, 0)); } - Array *arrs[] - = { + vector *arrs[] + = + { &item_indices, &spanner_indices }; - for (int i = 0; i < item_index;i++) + for (int i = 0; i < item_index; i++) { for (int j = vec[i].left_; j <= vec[i].right_; j++) - item_indices[j - system_range[LEFT]].add_point (i); + item_indices[j - system_range[LEFT]].add_point (i); } /* @@ -380,43 +366,43 @@ Spanner::fast_substitute_grob_array (SCM sym, is a waste of time -- the staff-spanners screw up the ordering, since they go across the entire score. */ - for (int i = spanner_indices.size (); i--;) + for (vsize i = spanner_indices.size (); i--;) spanner_indices[i] = Slice (spanner_index, len - 1); assert (item_index <= spanner_index); - assert ((broken_intos_.size () == system_range.length () + 1) - || (broken_intos_.is_empty () && system_range.length () == 0)); - for (int i = 0; i < broken_intos_.size (); i++) + assert ((broken_intos_.size () == (vsize)system_range.length () + 1) + || (broken_intos_.empty () && system_range.length () == 0)); + for (vsize i = 0; i < broken_intos_.size (); i++) { Grob *sc = broken_intos_[i]; System *l = sc->get_system (); set_break_subsititution (l ? l->self_scm () : SCM_UNDEFINED); SCM newval = sc->internal_get_object (sym); - if (!unsmob_grob_array (newval)) - { - newval = Grob_array::make_array (); - sc->internal_set_object (sym, newval); - } - - Grob_array *new_array = unsmob_grob_array (newval); - for (int k = 0; k < 2;k++) - for (int j = (*arrs[k])[i][LEFT]; j <= (*arrs[k])[i][RIGHT]; j++) - { - Grob *substituted = substitute_grob (vec[j].grob_); - if (substituted) - new_array->add (substituted); - } + if (!unsmob (newval)) + { + newval = Grob_array::make_array (); + sc->set_object (sym, newval); + } + + Grob_array *new_array = unsmob (newval); + for (int k = 0; k < 2; k++) + for (int j = (*arrs[k])[i][LEFT]; j <= (*arrs[k])[i][RIGHT]; j++) + { + Grob *substituted = substitute_grob (vec[j].grob_); + if (substituted) + new_array->add (substituted); + } #ifdef PARANOIA printf ("%d (%d), sp %d (%d)\n", - item_indices [i].length (), item_index, - spanner_indices[i].length (), len -spanner_index); + item_indices [i].length (), item_index, + spanner_indices[i].length (), len - spanner_index); { - SCM l1 = substitute_grob_list (grob_list); - assert (scm_ilength (l1) == scm_ilength (newval)); + SCM l1 = substitute_grob_list (grob_list); + assert (scm_ilength (l1) == scm_ilength (newval)); } #endif } @@ -447,68 +433,69 @@ substitute_object_alist (SCM alist, SCM dest) SCM sym = scm_caar (s); SCM val = scm_cdar (s); - if (Grob_array *orig = unsmob_grob_array (val)) - { - SCM handle = scm_assq (sym, dest); - SCM newval - = (scm_is_pair (handle)) - ? scm_cdr (handle) - : Grob_array::make_array (); - - Grob_array *new_arr = unsmob_grob_array (newval); - - substitute_grob_array (orig, new_arr); - val = newval; - } + if (Grob_array *orig = unsmob (val)) + { + SCM handle = scm_assq (sym, dest); + SCM newval + = (scm_is_pair (handle)) + ? scm_cdr (handle) + : Grob_array::make_array (); + + Grob_array *new_arr = unsmob (newval); + // TODO: What if new_arr is null? + new_arr->filter_map_assign (*orig, substitute_grob); + val = newval; + } else - val = do_break_substitution (val); - - if (val != SCM_UNDEFINED) - { - /* - for ly:grob? properties, SCM_UNDEFINED could leak out - through ly:grob-property - */ - *tail = scm_cons (scm_cons (sym, val), SCM_EOL); - tail = SCM_CDRLOC (*tail); - } + val = do_break_substitution (val); + + if (!SCM_UNBNDP (val)) + { + /* + for ly:grob? properties, SCM_UNDEFINED could leak out + through ly:grob-property + */ + *tail = scm_cons (scm_cons (sym, val), SCM_EOL); + tail = SCM_CDRLOC (*tail); + } } return l; } void Spanner::substitute_one_mutable_property (SCM sym, - SCM val) + SCM val) { Spanner *s = this; bool fast_done = false; - Grob_array *grob_array = unsmob_grob_array (val); + Grob_array *grob_array = unsmob (val); if (grob_array) fast_done = s->fast_substitute_grob_array (sym, grob_array); if (!fast_done) - for (int i = 0; i < s->broken_intos_.size (); i++) + for (vsize i = 0; i < s->broken_intos_.size (); i++) { - Grob *sc = s->broken_intos_[i]; - System *l = sc->get_system (); - set_break_subsititution (l ? l->self_scm () : SCM_UNDEFINED); - - if (grob_array) - { - SCM newval = sc->internal_get_object (sym); - if (!unsmob_grob_array (newval)) - { - newval = Grob_array::make_array (); - sc->internal_set_object (sym, newval); - } - substitute_grob_array (grob_array, unsmob_grob_array (newval)); - } - else - { - SCM newval = do_break_substitution (val); - sc->internal_set_object (sym, newval); - } + Grob *sc = s->broken_intos_[i]; + System *l = sc->get_system (); + set_break_subsititution (l ? l->self_scm () : SCM_UNDEFINED); + + if (grob_array) + { + SCM newval = sc->internal_get_object (sym); + if (!unsmob (newval)) + { + newval = Grob_array::make_array (); + sc->set_object (sym, newval); + } + Grob_array *new_arr = unsmob (newval); + new_arr->filter_map_assign (*grob_array, substitute_grob); + } + else + { + SCM newval = do_break_substitution (val); + sc->set_object (sym, newval); + } } }