2006-03-20 Han-Wen Nienhuys <hanwen@xs4all.nl>
+ * lily/break-align-interface.cc (self_align_callback): new
+ interface, new function. Look at complete alignment. This handles
+ tunable break alignments in case break-align-symbols are missing.
+
+ * lily/bar-number-engraver.cc (acknowledge_break_alignment): new function
+
+ * lily/mark-engraver.cc (acknowledge_break_alignment): new function.
+
+ * python/convertrules.py (conv): mark/bar number alignment rule.
+
+ * lily/break-align-interface.cc (calc_positioning_done): also
+ store offset from last visible break-alignment to its
+ neighbor. This makes alignment on non-visible objects more reliable.
+
* po/lilypond.pot (Module): ran po-replace.
* input/regression/tie-single-manual.ly (Module): new file.
\header {
texidoc = "The rehearsal mark is put on top a breakable symbol,
- according to the value of @code{rehearsalMarkAlignSymbol}."
+ according to the value of @code{break-align-symbol} value of the
+ @code{RehearsalMark}. The same holds for @code{BarNumber} grobs."
}
c1 \mark "foo"
\key cis \major
\clef alto
- \set Score.rehearsalMarkAlignSymbol = #'key-signature
+ \override Score.RehearsalMark #'break-align-symbol = #'key-signature
\mark "on-key"
cis
- \key ces \major
- \set Score.rehearsalMarkAlignSymbol = #'clef
+ \key ces \major
+ \override Score.RehearsalMark #'break-align-symbol = #'clef
\clef treble
\mark "on clef"
ces
protected:
void stop_translation_timestep ();
DECLARE_ACKNOWLEDGER (break_aligned);
+ DECLARE_ACKNOWLEDGER (break_alignment);
void process_music ();
void create_items ();
TRANSLATOR_DECLARATIONS (Bar_number_engraver);
text_ = 0;
}
+
+/*
+ see rehearsal mark comments.
+ */
void
Bar_number_engraver::acknowledge_break_aligned (Grob_info inf)
{
Grob *s = inf.grob ();
if (text_
+ && !text_->get_parent (X_AXIS)
&& dynamic_cast<Item *> (s)
- && s->get_property ("break-align-symbol") == get_property ("barNumberAlignSymbol"))
+ && (s->get_property_data (ly_symbol2scm ("break-align-symbol"))
+ == text_->get_property_data (ly_symbol2scm ("break-align-symbol"))))
{
/*
By default this would land on the Paper_column -- so why
}
}
+
+void
+Bar_number_engraver::acknowledge_break_alignment (Grob_info inf)
+{
+ Grob *s = inf.grob ();
+ if (text_
+ && dynamic_cast<Item *> (s))
+ {
+ text_->set_parent (s, X_AXIS);
+ }
+}
+
void
Bar_number_engraver::stop_translation_timestep ()
{
ADD_ACKNOWLEDGER(Bar_number_engraver,break_aligned);
+ADD_ACKNOWLEDGER(Bar_number_engraver,break_alignment);
ADD_TRANSLATOR (Bar_number_engraver,
/* doc */ "A bar number is created whenever measurePosition "
/* create */ "BarNumber",
/* accept */ "",
/* read */
- "barNumberAlignSymbol "
"currentBarNumber "
"whichBar "
"stavesFound "
So we return the correct order as an array.
*/
-vector<Grob*>
-Break_align_interface::ordered_elements (Grob *grob)
+SCM
+Break_align_interface::break_align_order (Item *me)
{
- Item *me = dynamic_cast<Item *> (grob);
- extract_grob_set (me, "elements", elts);
-
SCM order_vec = me->get_property ("break-align-orders");
if (!scm_is_vector (order_vec)
|| scm_c_vector_length (order_vec) < 3)
- return elts;
+ return SCM_BOOL_F;
- vector<Grob*> writable_elts (elts);
SCM order = scm_vector_ref (order_vec,
scm_from_int (me->break_status_dir () + 1));
- /*
+
+ return order;
+}
+
+
+vector<Grob*>
+Break_align_interface::ordered_elements (Grob *grob)
+{
+ Item *me = dynamic_cast<Item *> (grob);
+ extract_grob_set (me, "elements", elts);
+
+
+ SCM order = break_align_order (me);
+
+ if (order == SCM_BOOL_F)
+ return elts;
+
+ vector<Grob*> writable_elts (elts);
+ /*
Copy in order specified in BREAK-ALIGN-ORDER.
*/
vector<Grob*> new_elts;
Grob *elt = elts[i];
if (edge_idx == VPOS
- && elt->get_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_property ("space-alist");
offsets[next_idx] = max (extents[idx][RIGHT], distance);
}
else
- extra_right_space = distance;
+ {
+ extra_right_space = distance;
+ if (idx < offsets.size() - 1)
+ offsets[idx+1] = extents[idx][RIGHT] + distance;
+ }
idx = next_idx;
}
"positioning-done "
"break-align-orders");
+
+MAKE_SCHEME_CALLBACK(Break_alignment_align_interface, self_align_callback, 1)
+SCM
+Break_alignment_align_interface::self_align_callback (SCM grob)
+{
+ Grob *me = unsmob_grob (grob);
+ Item *alignment = dynamic_cast<Item*> (me->get_parent (X_AXIS));
+ if (!Break_align_interface::has_interface (alignment))
+ return scm_from_int (0);
+
+ SCM my_align = me->get_property ("break-align-symbol");
+ SCM order = Break_align_interface::break_align_order (alignment);
+
+ vector<Grob*> elements = Break_align_interface::ordered_elements (alignment);
+ if (elements.size () == 0)
+ return scm_from_int (0);
+
+ int last_idx_found = -1;
+ vsize i = 0;
+ for (SCM s = order; scm_is_pair (order); s = scm_cdr (s))
+ {
+ if (i < elements.size ()
+ && elements[i]->get_property ("break-align-symbol") == scm_car (s))
+ {
+ last_idx_found = i;
+ i ++;
+ }
+
+ if (scm_car (s) == my_align)
+ break ;
+ }
+
+ Direction which_edge = LEFT;
+ if (vsize (last_idx_found + 1) < elements.size())
+ last_idx_found ++;
+ else
+ which_edge = RIGHT;
+
+ Grob *common = me->common_refpoint (elements[last_idx_found], X_AXIS);
+
+ return scm_from_double (robust_relative_extent (elements[last_idx_found], common, X_AXIS)[which_edge]
+ - me->relative_coordinate (common, X_AXIS));
+}
+
+ADD_INTERFACE (Break_alignment_align_interface, "break-alignment-align-interface",
+ "Object that is aligned on a break aligment. ",
+
+ /* properties */
+ "break-align-symbol "
+ )
+
+
static vector<Grob*> ordered_elements (Grob *me);
static bool has_interface (Grob *);
static void add_element (Grob *me, Grob *add);
+ static SCM break_align_order (Item *me);
DECLARE_SCHEME_CALLBACK (calc_positioning_done, (SCM element));
DECLARE_SCHEME_CALLBACK (self_align_callback, (SCM element));
};
+
struct Break_aligned_interface
{
static bool has_interface (Grob *);
};
+struct Break_alignment_align_interface
+{
+ DECLARE_SCHEME_CALLBACK (self_align_callback, (SCM element));
+ static bool has_interface (Grob *);
+};
+
#endif // BREAK_ALIGN_INTERFACE_HH
void process_music ();
void stop_translation_timestep ();
+ DECLARE_ACKNOWLEDGER (break_alignment);
DECLARE_ACKNOWLEDGER (break_aligned);
};
mark_ev_ = 0;
}
+/*
+ This is a flawed approach, since various break-aligned objects may
+ not appear depending on key signature etc.
+
+ We keep it in case someone puts the engraver in a lower context than score.
+ */
void
Mark_engraver::acknowledge_break_aligned (Grob_info inf)
{
Grob *s = inf.grob ();
if (text_
- && (get_property ("rehearsalMarkAlignSymbol")
- == s->get_property ("break-align-symbol"))
+ && !text_->get_parent (X_AXIS)
+ && (text_->get_property_data (ly_symbol2scm ("break-align-symbol"))
+ == s->get_property_data (ly_symbol2scm ("break-align-symbol")))
&& Axis_group_interface::has_interface (s))
{
/*
}
}
+void
+Mark_engraver::acknowledge_break_alignment (Grob_info inf)
+{
+ Grob *s = inf.grob ();
+ if (text_
+ && dynamic_cast<Item *> (s))
+ {
+ text_->set_parent (s, X_AXIS);
+ }
+}
+
+
void
Mark_engraver::stop_translation_timestep ()
{
#include "translator.icc"
ADD_ACKNOWLEDGER (Mark_engraver, break_aligned);
+ADD_ACKNOWLEDGER (Mark_engraver, break_alignment);
ADD_TRANSLATOR (Mark_engraver,
/* doc */ "This engraver will create RehearsalMark objects. "
tupletNumberFormatFunction = #denominator-tuplet-formatter
markFormatter = #format-mark-letters
rehearsalMark = #1
- rehearsalMarkAlignSymbol = #'staff-bar
- barNumberAlignSymbol = #'staff-bar
subdivideBeams = ##f
allowBeamBreak = ##f
extraNatural = ##t
"""def-(music-function|markup-command) -> define-(music-function|markup-command)"""))
-conversions.append (((2, 7, 39), lambda x: x,
- "Minimum version for 2.8"))
+
+def conv (str):
+ str = re.sub (r'\\set\s+Score\s*\.\s*barNumberAlignSymbol\s*=',
+ r"\\override Score.BarNumber #'break-align-symbol = ", str)
+ str = re.sub (r'\\set\s*Score\s*\.\s*rehearsalMarkAlignSymbol\s*=',
+ r"\\override Score.RehearsalMark #'break-align-symbol = ", str)
+ return str
+
+conversions.append (((2, 7, 40), conv,
+ "rehearsalMarkAlignSymbol/barNumberAlignSymbol -> break-align-symbol"))
(font-size . -2)
(Y-offset . ,ly:side-position-interface::y-aligned-side)
(side-axis . ,Y)
- (X-offset . ,ly:self-alignment-interface::x-aligned-on-self)
- (self-alignment-X . 1)
+ (X-offset . ,(ly:make-simple-closure
+ `(,+
+ ,(ly:make-simple-closure
+ (list ly:break-alignment-align-interface::self-align-callback))
+ ,(ly:make-simple-closure
+ (list ly:self-alignment-interface::x-aligned-on-self)))))
+ (self-alignment-X . 1)
+ (break-align-symbol . left-edge)
(meta .
((class . Item)
(interfaces . (side-position-interface
text-interface
+ break-alignment-align-interface
self-alignment-interface
font-interface
- break-aligned-interface))))
+ ))))
))
(BassFigure
. (
(stencil . ,ly:text-interface::print)
(X-offset . ,(ly:make-simple-closure
- `(,+ ,(ly:make-simple-closure
- `(,ly:self-alignment-interface::x-aligned-on-self))
- ,(ly:make-simple-closure
- `(,ly:self-alignment-interface::centered-on-x-parent)))
- ))
+ `(,+
+ ,(ly:make-simple-closure
+ (list ly:break-alignment-align-interface::self-align-callback))
+ ,(ly:make-simple-closure
+ (list ly:self-alignment-interface::x-aligned-on-self)))))
+
(Y-offset . ,ly:side-position-interface::y-aligned-side)
(self-alignment-X . 0)
(direction . ,UP)
(font-size . 2)
(baseline-skip . 2)
(break-visibility . ,end-of-line-invisible)
+ (break-align-symbol . staff-bar)
(padding . 0.8)
(meta . ((class . Item)
(interfaces . (text-interface
side-position-interface
+ break-alignment-align-interface
font-interface
mark-interface
self-alignment-interface))))))