X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fbreak-substitution.cc;h=8326cee5eeb8f045a3bf1cbc46158c6432c2848a;hb=5b4b0d6e9a197e8f9eb085b7c2ad78b8be3e5cfc;hp=9afd8f13eaa40e1681718283beb6943448dc28dd;hpb=58bcc84c9480dae1b21bc24d8396b91fe19e0131;p=lilypond.git diff --git a/lily/break-substitution.cc b/lily/break-substitution.cc index 9afd8f13ea..8326cee5ee 100644 --- a/lily/break-substitution.cc +++ b/lily/break-substitution.cc @@ -1,8 +1,18 @@ +/* + break-substitution.cc -- implement grob break substitution. + + source file of the GNU LilyPond music typesetter + + (c) 2001--2008 Han-Wen Nienhuys +*/ + #include #include +using namespace std; #include "item.hh" #include "system.hh" +#include "grob-array.hh" static SCM break_criterion; void @@ -14,7 +24,7 @@ set_break_subsititution (SCM criterion) /* Perform the substitution for a single grob. */ -SCM +Grob * substitute_grob (Grob *sc) { if (scm_is_integer (break_criterion)) @@ -24,7 +34,7 @@ substitute_grob (Grob *sc) if (i && i->break_status_dir () != d) { Item *br = i->find_prebroken_piece (d); - return (br) ? br->self_scm () : SCM_UNDEFINED; + return br; } } else @@ -32,18 +42,15 @@ substitute_grob (Grob *sc) System *line = dynamic_cast (unsmob_grob (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 SCM_UNDEFINED; + return 0; /* now: sc && sc->get_system () == line */ if (!line) - return sc->self_scm (); + return sc; /* We don't return SCM_UNDEFINED for @@ -57,13 +64,11 @@ substitute_grob (Grob *sc) if (sc->common_refpoint (line, X_AXIS) && sc->common_refpoint (line, Y_AXIS)) - { - return sc->self_scm (); - } - return SCM_UNDEFINED; + return sc; + return 0; } - return sc->self_scm (); + return sc; } /* @@ -86,14 +91,17 @@ do_break_substitution (SCM src) again: if (unsmob_grob (src)) - return substitute_grob (unsmob_grob (src)); + { + Grob *new_ptr = substitute_grob (unsmob_grob (src)); + return new_ptr ? new_ptr->self_scm () : SCM_UNDEFINED; + } else if (scm_is_vector (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_int2num (i); + SCM si = scm_from_int (i); scm_vector_set_x (nv, si, do_break_substitution (scm_vector_ref (src, si))); } @@ -131,24 +139,29 @@ do_break_substitution (SCM src) /* Perform substitution on GROB_LIST using a constant amount of stack. */ -SCM -substitute_grob_list (SCM grob_list) +vector temporary_substition_array; +void +substitute_grob_array (Grob_array *grob_arr, Grob_array *new_arr) { - SCM l = SCM_EOL; - SCM *tail = &l; - - for (SCM s = grob_list; scm_is_pair (s); s = scm_cdr (s)) + vector &old_grobs (grob_arr->array_reference ()); + vector *new_grobs (new_arr == grob_arr + ? & temporary_substition_array + : &new_arr->array_reference ()); + + new_grobs->resize (old_grobs.size ()); + Grob **array = (Grob **) new_grobs->data (); + Grob **ptr = array; + for (vsize i = 0; i < old_grobs.size (); i++) { - SCM n = substitute_grob (unsmob_grob (scm_car (s))); - - if (n != SCM_UNDEFINED) - { - *tail = scm_cons (n, SCM_EOL); - tail = SCM_CDRLOC (*tail); - } + Grob *orig = old_grobs[i]; + Grob *new_grob = substitute_grob (orig); + if (new_grob) + *ptr++ = new_grob; } - return l; + new_grobs->resize (ptr - array); + if (new_arr == grob_arr) + new_arr->set_array (*new_grobs); } /* @@ -207,14 +220,12 @@ spanner_system_range (Spanner *sp) Slice rv; if (System *st = sp->get_system ()) - { - rv = Slice (st->rank_, st->rank_); - } + rv = Slice (st->get_rank (), st->get_rank ()); else { if (sp->broken_intos_.size ()) - rv = Slice (sp->broken_intos_[0]->get_system ()->rank_, - sp->broken_intos_.top ()->get_system ()->rank_); + rv = Slice (sp->broken_intos_[0]->get_system ()->get_rank (), + sp->broken_intos_.back ()->get_system ()->get_rank ()); } return rv; } @@ -223,7 +234,7 @@ Slice item_system_range (Item *it) { if (System *st = it->get_system ()) - return Slice (st->rank_, st->rank_); + return Slice (st->get_rank (), st->get_rank ()); Slice sr; Direction d = LEFT; @@ -231,9 +242,9 @@ item_system_range (Item *it) { Item *bi = it->find_prebroken_piece (d); if (bi && bi->get_system ()) - sr.add_point (bi->get_system ()->rank_); + sr.add_point (bi->get_system ()->get_rank ()); } - while (flip (&d)!= LEFT); + while (flip (&d) != LEFT); return sr; } @@ -252,6 +263,8 @@ grob_system_range (Grob *g) struct Substitution_entry { Grob *grob_; + + /* Assumption: we have less than 32k paper columns. */ short left_; short right_; @@ -298,22 +311,21 @@ struct Substitution_entry }; bool -Spanner::fast_fubstitute_grob_list (SCM sym, - SCM grob_list) +Spanner::fast_substitute_grob_array (SCM sym, + Grob_array *grob_array) { - int len = scm_ilength (grob_list); + int len = grob_array->size (); - /* - Only do this complicated thing for large lists. This has the added - advantage that we won't screw up the ordering for elements in - alignments (which typically don't have more than 10 grobs.) - */ + if (grob_array->ordered ()) + return false; - if (len < 300) + if (len < 15) return false; /* - TODO : should not free it some time? + 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; @@ -326,107 +338,91 @@ Spanner::fast_fubstitute_grob_list (SCM sym, Slice system_range = spanner_system_range (this); - Array it_indices; - Array sp_indices; - for (int i = 0; i <= system_range.length (); i++) - { - it_indices.push (Slice (len, 0)); - sp_indices.push (Slice (len, 0)); - } + int spanner_index = len; + int item_index = 0; - int sp_index = len; - int it_index = 0; - for (SCM s = grob_list; scm_is_pair (s); s = scm_cdr (s)) + for (vsize i = 0; i < grob_array->size (); i++) { - Grob *g = unsmob_grob (scm_car (s)); + Grob *g = grob_array->grob (i); Slice sr = grob_system_range (g); sr.intersect (system_range); int idx = 0; if (dynamic_cast (g)) - { - idx =--sp_index; - } + idx = --spanner_index; else if (dynamic_cast (g)) - { - idx = it_index++; - } + idx = item_index++; vec[idx].set (g, sr); } - qsort (vec, it_index, + qsort (vec, item_index, sizeof (Substitution_entry), &Substitution_entry::item_compare); - Array *arrs[] + vector item_indices; + vector spanner_indices; + for (int i = 0; i <= system_range.length (); i++) + { + item_indices.push_back (Slice (len, 0)); + spanner_indices.push_back (Slice (len, 0)); + } + + vector *arrs[] = { - &it_indices, &sp_indices + &item_indices, &spanner_indices }; - for (int i = 0; i < it_index;i++) + for (int i = 0; i < item_index;i++) { for (int j = vec[i].left_; j <= vec[i].right_; j++) - { - it_indices[j - system_range[LEFT]].add_point (i); - } + item_indices[j - system_range[LEFT]].add_point (i); } /* - sorting vec[sp_index.. len] + sorting vec[spanner_index.. len] is a waste of time -- the staff-spanners screw up the ordering, since they go across the entire score. */ - for (int i = sp_indices.size (); i--;) - sp_indices[i]= Slice (sp_index, len - 1); + for (vsize i = spanner_indices.size (); i--;) + spanner_indices[i] = Slice (spanner_index, len - 1); - assert (it_index <= sp_index); + assert (item_index <= spanner_index); - assert (broken_intos_.size () == system_range.length () + 1); - 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); + set_break_subsititution (l ? l->self_scm () : SCM_UNDEFINED); - SCM newval = SCM_EOL; - SCM *tail = &newval; + SCM newval = sc->internal_get_object (sym); + if (!unsmob_grob_array (newval)) + { + newval = Grob_array::make_array (); + sc->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++) { - SCM subs = substitute_grob (vec[j].grob_); - if (subs!= SCM_UNDEFINED) - { - *tail = scm_cons (subs, SCM_EOL); - - tail = SCM_CDRLOC (*tail); - } - + Grob *substituted = substitute_grob (vec[j].grob_); + if (substituted) + new_array->add (substituted); } #ifdef PARANOIA - printf ("%d (%d), sp %d (%d)\n", - it_indices [i].length (), it_index, - sp_indices[i].length (), len -sp_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)); } #endif - - /* - see below. - */ - if (sym == ly_symbol2scm ("all-elements")) - sc->mutable_property_alist_ - = scm_assq_remove_x (sc->mutable_property_alist_, - ly_symbol2scm ("all-elements")); - - sc->mutable_property_alist_ = scm_acons (sym, newval, - sc->mutable_property_alist_); } return true; @@ -446,20 +442,28 @@ Spanner::fast_fubstitute_grob_list (SCM sym, pthreads. pthreads impose small limits on the stack size. */ SCM -substitute_mutable_property_alist (SCM alist) +substitute_object_alist (SCM alist, SCM dest) { - SCM grob_list_p = ly_lily_module_constant ("grob-list?"); - SCM l = SCM_EOL; SCM *tail = &l; for (SCM s = alist; scm_is_pair (s); s = scm_cdr (s)) { SCM sym = scm_caar (s); SCM val = scm_cdar (s); - SCM type = scm_object_property (sym, ly_symbol2scm ("backend-type?")); - if (type == grob_list_p) - val = substitute_grob_list (val); + 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; + } else val = do_break_substitution (val); @@ -480,44 +484,41 @@ void Spanner::substitute_one_mutable_property (SCM sym, SCM val) { - SCM type = scm_object_property (sym, ly_symbol2scm ("backend-type?")); Spanner *s = this; bool fast_done = false; - SCM grob_list_p = ly_lily_module_constant ("grob-list?"); - if (type == grob_list_p) - fast_done = s->fast_fubstitute_grob_list (sym, val); + Grob_array *grob_array = unsmob_grob_array (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); - SCM newval = (type == grob_list_p) - ? substitute_grob_list (val) - : do_break_substitution (val); - - /* - For the substitution of a single property, we tack the result onto - mutable_property_alist_ ; mutable_property_alist_ is empty after - Grob::Grob (Grob const&), except that System has all-elements set, - as a side product of typeset_grob () on newly copied spanners. - - Here we clear that list explicitly to free some memory and - counter some of the confusion I encountered while debugging - another problem - - (hwn 4/2/04) - */ - if (sym == ly_symbol2scm ("all-elements")) - sc->mutable_property_alist_ - = scm_assq_remove_x (sc->mutable_property_alist_, - ly_symbol2scm ("all-elements")); - - sc->mutable_property_alist_ = scm_cons (scm_cons (sym, newval), - sc->mutable_property_alist_); + if (grob_array) + { + SCM newval = sc->internal_get_object (sym); + if (!unsmob_grob_array (newval)) + { + newval = Grob_array::make_array (); + sc->set_object (sym, newval); + } + substitute_grob_array (grob_array, unsmob_grob_array (newval)); + } + else + { + SCM newval = do_break_substitution (val); + sc->set_object (sym, newval); + } } } +void +Grob::substitute_object_links (SCM crit, SCM orig) +{ + set_break_subsititution (crit); + object_alist_ = substitute_object_alist (orig, object_alist_); +}