X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fbreak-alignment-interface.cc;h=a1d7606445353ece111cbf221a4bc9eda9257f53;hb=a6a51abfd0195a3cf7d6ea095cf69808852f21ce;hp=a5c6679bea491ab1f2ccfcfedd533adb99987531;hpb=ecf2b5e9dcfa7654803fb0050d7127e0ec7fd934;p=lilypond.git diff --git a/lily/break-alignment-interface.cc b/lily/break-alignment-interface.cc index a5c6679bea..a1d7606445 100644 --- a/lily/break-alignment-interface.cc +++ b/lily/break-alignment-interface.cc @@ -1,11 +1,21 @@ /* - break-align-interface.cc -- implement Break_alignment_interface + This file is part of LilyPond, the GNU music typesetter. - source file of the GNU LilyPond music typesetter + Copyright (C) 1997--2015 Han-Wen Nienhuys - (c) 1997--2007 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 "break-align-interface.hh" @@ -16,12 +26,9 @@ #include "output-def.hh" #include "paper-column.hh" #include "pointer-group-interface.hh" -#include "self-alignment-interface.hh" #include "side-position-interface.hh" #include "warn.hh" - - /* This is tricky: we cannot modify 'elements, since callers are iterating the same list. Reordering the list in-place, or resetting @@ -38,43 +45,40 @@ Break_alignment_interface::break_align_order (Item *me) return SCM_BOOL_F; SCM order = scm_vector_ref (order_vec, - scm_from_int (me->break_status_dir () + 1)); - + scm_from_int (me->break_status_dir () + 1)); return order; } - -vector +vector Break_alignment_interface::ordered_elements (Grob *grob) { Item *me = dynamic_cast (grob); extract_grob_set (me, "elements", elts); - SCM order = break_align_order (me); - if (order == SCM_BOOL_F) + if (scm_is_false (order)) return elts; - - vector writable_elts (elts); - /* - Copy in order specified in BREAK-ALIGN-ORDER. + + vector writable_elts (elts); + /* + Copy in order specified in BREAK-ALIGN-ORDER. */ - vector new_elts; + vector new_elts; for (; scm_is_pair (order); order = scm_cdr (order)) { SCM sym = scm_car (order); for (vsize i = writable_elts.size (); i--;) - { - Grob *g = writable_elts[i]; - if (g && sym == g->get_property ("break-align-symbol")) - { - new_elts.push_back (g); - writable_elts.erase (writable_elts.begin () + i); - } - } + { + Grob *g = writable_elts[i]; + if (g && scm_is_eq (sym, g->get_property ("break-align-symbol"))) + { + new_elts.push_back (g); + writable_elts.erase (writable_elts.begin () + i); + } + } } return new_elts; @@ -90,22 +94,18 @@ MAKE_SCHEME_CALLBACK (Break_alignment_interface, calc_positioning_done, 1) SCM Break_alignment_interface::calc_positioning_done (SCM smob) { - Grob *grob = unsmob_grob (smob); + Grob *grob = unsmob (smob); Item *me = dynamic_cast (grob); - me->set_property ("positioning-done", SCM_BOOL_T); - vector elems = ordered_elements (me); + vector elems = ordered_elements (me); vector extents; - int last_nonempty = -1; for (vsize i = 0; i < elems.size (); i++) { Interval y = elems[i]->extent (elems[i], X_AXIS); extents.push_back (y); - if (!y.is_empty ()) - last_nonempty = i; } vsize idx = 0; @@ -114,7 +114,7 @@ Break_alignment_interface::calc_positioning_done (SCM smob) vector offsets; offsets.resize (elems.size ()); - for (vsize i = 0; i < offsets.size ();i++) + for (vsize i = 0; i < offsets.size (); i++) offsets[i] = 0.0; Real extra_right_space = 0.0; @@ -123,106 +123,106 @@ Break_alignment_interface::calc_positioning_done (SCM smob) { vsize next_idx = idx + 1; while (next_idx < elems.size () - && extents[next_idx].is_empty ()) - next_idx++; + && extents[next_idx].is_empty ()) + next_idx++; Grob *l = elems[idx]; Grob *r = 0; if (next_idx < elems.size ()) - r = elems[next_idx]; + r = elems[next_idx]; SCM alist = SCM_EOL; /* - Find the first grob with a space-alist entry. + Find the first grob with a space-alist entry. */ extract_grob_set (l, "elements", elts); for (vsize i = elts.size (); i--;) - { - Grob *elt = elts[i]; - - if (edge_idx == VPOS - && (elt->get_property ("break-align-symbol") - == ly_symbol2scm ("left-edge"))) - edge_idx = idx; - - SCM l = elt->get_property ("space-alist"); - if (scm_is_pair (l)) - { - alist = l; - break; - } - } + { + Grob *elt = elts[i]; + + if (edge_idx == VPOS + && scm_is_eq (elt->get_property ("break-align-symbol"), + ly_symbol2scm ("left-edge"))) + edge_idx = idx; + + SCM l = elt->get_property ("space-alist"); + if (scm_is_pair (l)) + { + alist = l; + break; + } + } SCM rsym = r ? SCM_EOL : ly_symbol2scm ("right-edge"); /* - We used to use #'cause to find out the symbol and the spacing - table, but that gets icky when that grob is suicided for some - reason. + We used to use #'cause to find out the symbol and the spacing + table, but that gets icky when that grob is suicided for some + reason. */ if (r) - { - extract_grob_set (r, "elements", elts); - for (vsize i = elts.size (); - !scm_is_symbol (rsym) && i--;) - { - Grob *elt = elts[i]; - rsym = elt->get_property ("break-align-symbol"); - } - } - - if (rsym == ly_symbol2scm ("left-edge")) - edge_idx = next_idx; + { + extract_grob_set (r, "elements", elts); + for (vsize i = elts.size (); + !scm_is_symbol (rsym) && i--;) + { + Grob *elt = elts[i]; + rsym = elt->get_property ("break-align-symbol"); + } + } + + if (scm_is_eq (rsym, ly_symbol2scm ("left-edge"))) + edge_idx = next_idx; SCM entry = SCM_EOL; if (scm_is_symbol (rsym)) - entry = scm_assq (rsym, alist); + entry = scm_assq (rsym, alist); bool entry_found = scm_is_pair (entry); if (!entry_found) - { - string sym_string; - if (scm_is_symbol (rsym)) - sym_string = ly_symbol2string (rsym); + { + string sym_string; + if (scm_is_symbol (rsym)) + sym_string = ly_symbol2string (rsym); - string orig_string; - if (unsmob_grob (l->get_property ("cause"))) - orig_string = unsmob_grob (l->get_property ("cause"))->name (); + string orig_string; + if (unsmob (l->get_property ("cause"))) + orig_string = unsmob (l->get_property ("cause"))->name (); - programming_error (_f ("No spacing entry from %s to `%s'", - orig_string.c_str (), - sym_string.c_str ())); - } + programming_error (to_string ("No spacing entry from %s to `%s'", + orig_string.c_str (), + sym_string.c_str ())); + } Real distance = 1.0; SCM type = ly_symbol2scm ("extra-space"); if (entry_found) - { - entry = scm_cdr (entry); + { + entry = scm_cdr (entry); - distance = scm_to_double (scm_cdr (entry)); - type = scm_car (entry); - } + distance = scm_to_double (scm_cdr (entry)); + type = scm_car (entry); + } if (r) - { - if (type == ly_symbol2scm ("extra-space")) - offsets[next_idx] = extents[idx][RIGHT] + distance - - extents[next_idx][LEFT]; - /* should probably junk minimum-space */ - else if (type == ly_symbol2scm ("minimum-space")) - offsets[next_idx] = max (extents[idx][RIGHT], distance); - } + { + if (scm_is_eq (type, ly_symbol2scm ("extra-space"))) + offsets[next_idx] = extents[idx][RIGHT] + distance + - extents[next_idx][LEFT]; + /* should probably junk minimum-space */ + else if (scm_is_eq (type, ly_symbol2scm ("minimum-space"))) + offsets[next_idx] = max (extents[idx][RIGHT], distance); + } else - { - extra_right_space = distance; - if (idx + 1 < offsets.size ()) - offsets[idx+1] = extents[idx][RIGHT] + distance; - } + { + extra_right_space = distance; + if (idx + 1 < offsets.size ()) + offsets[idx + 1] = extents[idx][RIGHT] + distance; + } idx = next_idx; } @@ -235,7 +235,7 @@ Break_alignment_interface::calc_positioning_done (SCM smob) { here += offsets[i]; if (i == edge_idx) - alignment_off = -here; + alignment_off = -here; total_extent.unite (extents[i] + here); } @@ -257,40 +257,39 @@ Break_alignment_interface::calc_positioning_done (SCM smob) return SCM_BOOL_T; } - - MAKE_SCHEME_CALLBACK (Break_alignable_interface, self_align_callback, 1) SCM Break_alignable_interface::self_align_callback (SCM grob) { - Grob *me = unsmob_grob (grob); - Item *alignment = dynamic_cast (me->get_parent (X_AXIS)); - if (!Break_alignment_interface::has_interface (alignment)) + Grob *me = unsmob (grob); + Item *alignment = dynamic_cast (me->get_parent (X_AXIS)); + if (!has_interface (alignment)) return scm_from_int (0); SCM symbol_list = me->get_property ("break-align-symbols"); - vector elements = Break_alignment_interface::ordered_elements (alignment); + vector elements = Break_alignment_interface::ordered_elements (alignment); if (elements.size () == 0) return scm_from_int (0); - + int break_aligned_grob = -1; for (; scm_is_pair (symbol_list); symbol_list = scm_cdr (symbol_list)) { SCM sym = scm_car (symbol_list); for (vsize i = 0; i < elements.size (); i++) - { - if (elements[i]->get_property ("break-align-symbol") == sym) - { - if (Item::break_visible (elements[i]) - && !elements[i]->extent (elements[i], X_AXIS).is_empty ()) - { - break_aligned_grob = i; - goto found_break_aligned_grob; /* ugh. need to break out of 2 loops */ - } - else if (break_aligned_grob == -1) - break_aligned_grob = i; - } - } + { + if (scm_is_eq (sym, elements[i]->get_property ("break-align-symbol"))) + { + if (Item::break_visible (elements[i]) + // TODO SCM: simplify syntax? + && !elements[i]->extent (elements[i], X_AXIS).is_empty ()) + { + break_aligned_grob = i; + goto found_break_aligned_grob; /* ugh. need to break out of 2 loops */ + } + else if (break_aligned_grob == -1) + break_aligned_grob = i; + } + } } found_break_aligned_grob: @@ -302,15 +301,15 @@ found_break_aligned_grob: Real anchor = robust_scm2double (alignment_parent->get_property ("break-align-anchor"), 0); return scm_from_double (alignment_parent->relative_coordinate (common, X_AXIS) - - me->relative_coordinate (common, X_AXIS) - + anchor); + - me->relative_coordinate (common, X_AXIS) + + anchor); } MAKE_SCHEME_CALLBACK (Break_aligned_interface, calc_average_anchor, 1) SCM Break_aligned_interface::calc_average_anchor (SCM grob) { - Grob *me = unsmob_grob (grob); + Grob *me = unsmob (grob); Real avg = 0.0; int count = 0; @@ -320,10 +319,10 @@ Break_aligned_interface::calc_average_anchor (SCM grob) { SCM anchor = elts[i]->get_property ("break-align-anchor"); if (scm_is_number (anchor)) - { - count++; - avg += scm_to_double (anchor); - } + { + count++; + avg += scm_to_double (anchor); + } } return scm_from_double (count > 0 ? avg / count : 0); @@ -333,7 +332,7 @@ MAKE_SCHEME_CALLBACK (Break_aligned_interface, calc_extent_aligned_anchor, 1) SCM Break_aligned_interface::calc_extent_aligned_anchor (SCM smob) { - Grob *me = unsmob_grob (smob); + Grob *me = unsmob (smob); Real alignment = robust_scm2double (me->get_property ("break-align-anchor-alignment"), 0.0); Interval iv = me->extent (me, X_AXIS); @@ -347,70 +346,74 @@ MAKE_SCHEME_CALLBACK (Break_aligned_interface, calc_break_visibility, 1) SCM Break_aligned_interface::calc_break_visibility (SCM smob) { - /* a BreakAlignGroup is break-visible iff it has one element that is break-visible */ - Grob *me = unsmob_grob (smob); + /* a BreakAlignGroup is break-visible if it has one element that is break-visible */ + Grob *me = unsmob (smob); SCM ret = scm_c_make_vector (3, SCM_EOL); extract_grob_set (me, "elements", elts); for (int dir = 0; dir <= 2; dir++) { bool visible = false; for (vsize i = 0; i < elts.size (); i++) - { - SCM vis = elts[i]->get_property ("break-visibility"); - if (scm_is_vector (vis) && to_boolean (scm_c_vector_ref (vis, dir))) - visible = true; - } + { + SCM vis = elts[i]->get_property ("break-visibility"); + if (scm_is_vector (vis) && to_boolean (scm_c_vector_ref (vis, dir))) + visible = true; + } scm_c_vector_set_x (ret, dir, scm_from_bool (visible)); } return ret; } +ADD_INTERFACE (Break_alignment_interface, + "The object that performs break alignment.\n" + "\n" + "Three interfaces deal specifically with break alignment:\n" + "@enumerate\n" + "@item break-alignment-interface (this one),\n" + "@item @ref{break-alignable-interface}, and\n" + "@item @ref{break-aligned-interface}.\n" + "@end enumerate\n" + "\n" + " Each of these interfaces supports grob properties that use" + " @w{@emph{break-align symbols}}, which are Scheme symbols that" + " are used to specify the alignment, ordering, and spacing of" + " certain notational elements (@q{breakable}@tie{}items)." + "\n" + "@subsubheading Available break-align symbols:\n" + "\n" + "@example\n" + "ambitus\n" + "breathing-sign\n" + "clef\n" + "cue-clef\n" + "cue-end-clef\n" + "custos\n" + "key-cancellation\n" + "key-signature\n" + "left-edge\n" + "staff-bar\n" + "time-signature\n" + "@end example", + + /* properties */ + "positioning-done " + "break-align-orders " + ); + ADD_INTERFACE (Break_alignable_interface, - "Object that is aligned on a break aligment.", + "Object that is aligned on a break alignment.", - /* properties */ - "break-align-symbols " - ); + /* properties */ + "break-align-symbols " + "non-break-align-symbols " + ); ADD_INTERFACE (Break_aligned_interface, - "Items that are aligned in prefatory matter.\n" - "\n" - "The spacing of these items is controlled by the" - " @code{space-alist} property. It contains a list" - " @code{break-align-symbol}s with a specification of the" - " associated space. The space specification can be\n" - "\n" - "@table @code\n" - "@item (minimum-space . @var{spc}))\n" - "Pad space until the distance is @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." - " (does not work at start of line. fixme)\n" - "@item (extra-space . @var{spc})\n" - "Add @var{spc} amount of space.\n" - "@end table\n" - "\n" - "Special keys for the alist are @code{first-note} and" - " @code{next-note}, signifying 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." - " See [Wanske] page 126--134, [Ross] page 143--147.", - - /* properties */ - "break-align-anchor " - "break-align-anchor-alignment " - "break-align-symbol " - "space-alist " - ); - -ADD_INTERFACE (Break_alignment_interface, - "The object that performs break aligment. See" - " @ref{break-aligned-interface}.", - - /* properties */ - "positioning-done " - "break-align-orders " - ); + "Breakable items.", + + /* properties */ + "break-align-anchor " + "break-align-anchor-alignment " + "break-align-symbol " + "space-alist " + );