X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fbreak-align-interface.cc;h=b8c5c739ababb620b7eb2e20967c3f5524800d96;hb=e2a4be3b72b1c473658436e4f82234b401dd7b60;hp=dcef533e757d5149fc05d7bfe2481538f5111be2;hpb=ff498ed01dc80778ac61254566dc811301741003;p=lilypond.git diff --git a/lily/break-align-interface.cc b/lily/break-align-interface.cc index dcef533e75..b8c5c739ab 100644 --- a/lily/break-align-interface.cc +++ b/lily/break-align-interface.cc @@ -3,7 +3,7 @@ source file of the GNU LilyPond music typesetter - (c) 1997--2003 Han-Wen Nienhuys + (c) 1997--2004 Han-Wen Nienhuys */ @@ -28,17 +28,17 @@ SCM Break_align_interface::alignment_callback (SCM element_smob, SCM axis) { Grob *me = unsmob_grob (element_smob); - Axis a = (Axis) gh_scm2int (axis); + Axis a = (Axis) ly_scm2int (axis); assert (a == X_AXIS); Grob *par = me->get_parent (a); - if (par && !to_boolean (par->get_grob_property ("break-alignment-done"))) + if (par && !to_boolean (par->get_property ("positioning-done"))) { - par->set_grob_property ("break-alignment-done", SCM_BOOL_T); + par->set_property ("positioning-done", SCM_BOOL_T); Break_align_interface::do_alignment (par); } - return gh_double2scm (0); + return scm_make_real (0); } MAKE_SCHEME_CALLBACK (Break_align_interface,self_align_callback,2); @@ -46,14 +46,14 @@ SCM Break_align_interface::self_align_callback (SCM element_smob, SCM axis) { Grob *me = unsmob_grob (element_smob); - Axis a = (Axis) gh_scm2int (axis); + Axis a = (Axis) ly_scm2int (axis); assert (a == X_AXIS); Item* item = dynamic_cast (me); Direction bsd = item->break_status_dir (); if (bsd == LEFT) { - me->set_grob_property ("self-alignment-X", scm_int2num (RIGHT)); + me->set_property ("self-alignment-X", scm_int2num (RIGHT)); } /* @@ -62,6 +62,49 @@ Break_align_interface::self_align_callback (SCM element_smob, SCM axis) return Self_alignment_interface::aligned_on_self (element_smob, axis); } + +/* + This is tricky: we cannot modify 'elements, since callers are + iterating the same list. Reordering the list in-place, or resetting + 'elements will skip elements in the loops of callers. + + So we return the correct order as an array. + */ +Link_array +Break_align_interface::ordered_elements (Grob *grob) +{ + Item *me = dynamic_cast (grob); + SCM elts = me->get_property ("elements"); + SCM order_vec = me->get_property ("break-align-orders"); + if (!ly_c_vector_p (order_vec) + || ly_vector_length (order_vec) < 3) + return Pointer_group_interface__extract_grobs (me, (Grob*)0, + "elements"); + SCM order = scm_vector_ref (order_vec, + scm_int2num (me->break_status_dir() + 1)); + + + /* + Copy in order specified in BREAK-ALIGN-ORDER. + */ + Link_array new_elts; + for (; ly_c_pair_p (order); order = ly_cdr (order)) + { + SCM sym = ly_car (order); + + for (SCM s =elts; ly_c_pair_p (s); s = ly_cdr (s)) + { + Grob *g = unsmob_grob (ly_car (s)); + if (g && sym == g->get_property ("break-align-symbol")) + { + new_elts.push (g); + elts = scm_delq (g->self_scm (), elts); + } + } + } + return new_elts; +} + void Break_align_interface::add_element (Grob*me, Grob *toadd) { @@ -69,12 +112,12 @@ Break_align_interface::add_element (Grob*me, Grob *toadd) } void -Break_align_interface::do_alignment (Grob *me) +Break_align_interface::do_alignment (Grob *grob) { - Item * item = dynamic_cast (me); - Link_array elems - = Pointer_group_interface__extract_grobs (me, (Grob*)0, - "elements"); + Item * me = dynamic_cast (grob); + + + Link_array elems = ordered_elements (me); Array extents; int last_nonempty = -1; @@ -91,24 +134,24 @@ Break_align_interface::do_alignment (Grob *me) idx++; Array offsets; - offsets.set_size (elems.size()); - for (int i= 0; i < offsets.size();i ++) + offsets.set_size (elems.size ()); + for (int i= 0; i < offsets.size ();i ++) offsets[i] = 0.0; Real extra_right_space = 0.0; int edge_idx = -1; - while (idx < elems.size()) + while (idx < elems.size ()) { int next_idx = idx+1; - while (next_idx < elems.size() && + while (next_idx < elems.size () && extents[next_idx].is_empty () ) next_idx++; Grob *l = elems[idx]; Grob *r = 0; - if (next_idx < elems.size()) + if (next_idx < elems.size ()) r = elems[next_idx]; SCM alist = SCM_EOL; @@ -117,18 +160,18 @@ Break_align_interface::do_alignment (Grob *me) /* Find the first grob with a space-alist entry. */ - for (SCM s= l->get_grob_property ("elements"); - gh_pair_p (s) ; s = gh_cdr (s)) + for (SCM s = l->get_property ("elements"); + ly_c_pair_p (s) ; s = ly_cdr (s)) { - Grob *elt = unsmob_grob (gh_car (s)); + Grob *elt = unsmob_grob (ly_car (s)); if (edge_idx < 0 - && elt->get_grob_property ("break-align-symbol") - == ly_symbol2scm( "left-edge")) + && elt->get_property ("break-align-symbol") + == ly_symbol2scm ( "left-edge")) edge_idx = idx; - SCM l =elt->get_grob_property ("space-alist"); - if (gh_pair_p(l)) + SCM l =elt->get_property ("space-alist"); + if (ly_c_pair_p (l)) { alist= l; break; @@ -142,33 +185,33 @@ Break_align_interface::do_alignment (Grob *me) table, but that gets icky when that grob is suicided for some reason. */ - for (SCM s = r ? r->get_grob_property ("elements") : SCM_EOL; - !gh_symbol_p (rsym) && gh_pair_p (s); s = gh_cdr (s)) + for (SCM s = r ? r->get_property ("elements") : SCM_EOL; + !ly_c_symbol_p (rsym) && ly_c_pair_p (s); s = ly_cdr (s)) { - Grob * elt =unsmob_grob(gh_car (s)); + Grob * elt =unsmob_grob (ly_car (s)); - rsym = elt->get_grob_property ("break-align-symbol"); + rsym = elt->get_property ("break-align-symbol"); } - if (rsym == ly_symbol2scm("left-edge")) + if (rsym == ly_symbol2scm ("left-edge")) edge_idx = next_idx; SCM entry = SCM_EOL; - if (gh_symbol_p (rsym)) + if (ly_c_symbol_p (rsym)) entry = scm_assq (rsym, alist); - bool entry_found = gh_pair_p (entry); + bool entry_found = ly_c_pair_p (entry); if (!entry_found) { String sym_string; - if(gh_symbol_p (rsym)) + if (ly_c_symbol_p (rsym)) sym_string = ly_symbol2string (rsym); String orig_string ; - if (unsmob_grob (l->get_grob_property ("cause"))) - orig_string = unsmob_grob (l->get_grob_property ("cause"))->name (); + if (unsmob_grob (l->get_property ("cause"))) + orig_string = unsmob_grob (l->get_property ("cause"))->name (); - programming_error (_f("No spacing entry from %s to `%s'", + programming_error (_f ("No spacing entry from %s to `%s'", orig_string.to_str0 (), sym_string.to_str0 ())); } @@ -178,10 +221,10 @@ Break_align_interface::do_alignment (Grob *me) if (entry_found) { - entry = gh_cdr (entry); + entry = ly_cdr (entry); - distance = gh_scm2double (gh_cdr (entry)); - type = gh_car (entry) ; + distance = ly_scm2double (ly_cdr (entry)); + type = ly_car (entry) ; } if (r) @@ -190,7 +233,7 @@ Break_align_interface::do_alignment (Grob *me) offsets[next_idx] = extents[idx][RIGHT] + distance - extents[next_idx][LEFT]; /* should probably junk minimum-space */ - else if (type == ly_symbol2scm("minimum-space")) + else if (type == ly_symbol2scm ("minimum-space")) offsets[next_idx] = extents[idx][RIGHT] >? distance; } else @@ -205,7 +248,7 @@ Break_align_interface::do_alignment (Grob *me) Interval total_extent; Real alignment_off =0.0; - for (int i =0 ; i < offsets.size(); i++) + for (int i =0 ; i < offsets.size (); i++) { here += offsets[i]; if (i == edge_idx) @@ -214,7 +257,7 @@ Break_align_interface::do_alignment (Grob *me) } - if (item->break_status_dir () == LEFT) + if (me->break_status_dir () == LEFT) { alignment_off = - total_extent[RIGHT] - extra_right_space; } @@ -222,7 +265,7 @@ Break_align_interface::do_alignment (Grob *me) alignment_off = -total_extent[LEFT]; here = alignment_off; - for (int i =0 ; i < offsets.size(); i++) + for (int i =0 ; i < offsets.size (); i++) { here += offsets[i]; elems[i]->translate_axis (here, X_AXIS); @@ -233,13 +276,13 @@ Break_align_interface::do_alignment (Grob *me) ADD_INTERFACE (Break_aligned_interface, "break-aligned-interface", "Items that are aligned in prefatory matter.\n" "\n" - "The spacing of these items is controlled by the space-alist\n" - "property. It contains a list break-align-symbols with a specification\n" + "The spacing of these items is controlled by the @code{space-alist}\n" + "property. It contains a list @code{break-align-symbol}s with a specification\n" "of the associated space. The space specification can be " "@table @code\n" "@item (minimum-space . @var{spc}))\n" " Pad space until the distance is @var{spc}\n" - "@item (fixed-space} . @var{spc})\n" + "@item (fixed-space . @var{spc})\n" " Set a fixed space\n" "@item (semi-fixed-space . @var{spc})\n" " Set a space. Half of it is fixed and half is stretchable. \n" @@ -248,16 +291,16 @@ ADD_INTERFACE (Break_aligned_interface, "break-aligned-interface", " Add @var{spc} amount of space.\n" "@end table\n" "\n" - "Special keys for the alist are 'first-note and 'next-note, signifying\n" + "Special keys for the alist are @code{first-note} and @code{next-note}, signifying\n" "the first note on a line, and the next note halfway a line.\n" "\n" "Rules for this spacing are much more complicated than this. \n" "See [Wanske] page 126 -- 134, [Ross] pg 143 -- 147\n", - "break-align-symbol break-alignment-done space-alist"); + "break-align-symbol space-alist"); ADD_INTERFACE (Break_align_interface, "break-alignment-interface", - "See @ref{break-aligned-interface}.", - "break-alignment-done"); + "The object that performs break aligment. See @ref{break-aligned-interface}.", + "positioning-done break-align-orders");