summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHan-Wen Nienhuys <hanwen@xs4all.nl>2005-09-12 12:20:26 +0000
committerHan-Wen Nienhuys <hanwen@xs4all.nl>2005-09-12 12:20:26 +0000
commit4bee689d7993ecf9af95d33c7f8f4ecd8d74a3cc (patch)
tree70af25e6005508394eeb3eb0b1e11fcf635ba959
parent7eec42b50cda1f53fa25414abf07280c01f7753e (diff)
downloadlilypond-4bee689d7993ecf9af95d33c7f8f4ecd8d74a3cc.tar.gz
* Documentation/user/instrument-notation.itely (Laissez vibrer
ties): new node. * input/regression/laissez-vibrer-ties.ly: new file. * lily/laissez-vibrer-engraver.cc: new file. * lily/include/tie-column-format.hh: new file. * lily/tie-column-format.cc: new file. * lily/tie-column.cc (set_manual_tie_configuration): new function. * lily/laissez-vibrer-tie.cc: new file. * lily/include/laissez-vibrer-tie.hh: new file. * ly/engraver-init.ly: add Laissez_vibrer_engraver * ly/declarations-init.ly (laissezVibrer): add \laissezVibrer * scm/define-grobs.scm (all-grob-descriptions): add LaissezVibrerTie, LaissezVibrerTieColumn * lily/tie-column.cc (set_tie_config_directions): new function (final_shape_adjustment): new function. (shift_small_ties): new function. * scm/define-music-types.scm (music-descriptions): add LaissezVibrerEvent * lily/include/tie.hh (struct Tie_details): add x_gap_ (struct Tie_configuration): add head_position_ * lily/tie-column.cc (set_chord_outline): new function. * mf/cmr.enc.in: remove file.
-rw-r--r--ChangeLog39
-rw-r--r--Documentation/topdocs/NEWS.tely9
-rw-r--r--Documentation/user/instrument-notation.itely27
-rw-r--r--THANKS1
-rw-r--r--input/regression/laissez-vibrer-ties.ly31
-rw-r--r--lily/include/laissez-vibrer-tie-column.hh24
-rw-r--r--lily/include/laissez-vibrer-tie.hh28
-rw-r--r--lily/include/lily-proto.hh3
-rw-r--r--lily/include/tie-column-format.hh39
-rw-r--r--lily/include/tie.hh5
-rw-r--r--lily/include/translator.icc1
-rw-r--r--lily/laissez-vibrer-engraver.cc86
-rw-r--r--lily/laissez-vibrer-tie-column.cc126
-rw-r--r--lily/laissez-vibrer-tie.cc80
-rw-r--r--lily/tie-column-format.cc284
-rw-r--r--lily/tie-column.cc272
-rw-r--r--lily/tie.cc17
-rw-r--r--ly/declarations-init.ly3
-rw-r--r--ly/engraver-init.ly2
-rw-r--r--mf/GNUmakefile2
-rw-r--r--mf/cmr.enc.in36
-rw-r--r--scm/define-grobs.scm20
-rw-r--r--scm/define-music-types.scm8
23 files changed, 824 insertions, 319 deletions
diff --git a/ChangeLog b/ChangeLog
index 4480150..4061db9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,42 @@
+2005-09-12 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+ * Documentation/user/instrument-notation.itely (Laissez vibrer
+ ties): new node.
+
+ * input/regression/laissez-vibrer-ties.ly: new file.
+
+ * lily/laissez-vibrer-engraver.cc: new file.
+
+ * lily/include/tie-column-format.hh: new file.
+
+ * lily/tie-column-format.cc: new file.
+
+ * lily/tie-column.cc (set_manual_tie_configuration): new function.
+
+ * lily/laissez-vibrer-tie.cc: new file.
+
+ * lily/include/laissez-vibrer-tie.hh: new file.
+
+ * ly/engraver-init.ly: add Laissez_vibrer_engraver
+
+ * ly/declarations-init.ly (laissezVibrer): add \laissezVibrer
+
+ * scm/define-grobs.scm (all-grob-descriptions): add
+ LaissezVibrerTie, LaissezVibrerTieColumn
+
+ * lily/tie-column.cc (set_tie_config_directions): new function
+ (final_shape_adjustment): new function.
+ (shift_small_ties): new function.
+
+ * scm/define-music-types.scm (music-descriptions): add LaissezVibrerEvent
+
+ * lily/include/tie.hh (struct Tie_details): add x_gap_
+ (struct Tie_configuration): add head_position_
+
+ * lily/tie-column.cc (set_chord_outline): new function.
+
+ * mf/cmr.enc.in: remove file.
+
2005-09-11 Graham Percival <gpermus@gmail.com>
* Documentation/user/examples.itely: typo fix. Thanks, Matevž
diff --git a/Documentation/topdocs/NEWS.tely b/Documentation/topdocs/NEWS.tely
index 424d593..03c191c 100644
--- a/Documentation/topdocs/NEWS.tely
+++ b/Documentation/topdocs/NEWS.tely
@@ -47,6 +47,15 @@ This document is also available in @uref{NEWS.pdf,PDF}.
@itemize @bullet
@item
+Laissez vibrer ties can be created with @code{\laissezVibrer},
+
+@lilypond[fragment,raggedright,relative=1]
+ <c e g>\laissezVibrer <d f>\laissezVibrer
+@end lilypond
+
+This feature was sponsored by Henrik Frisk.
+
+@item
The order of words in @code{\markup} commands may now be reversed by
setting the @code{text-direction} property. This is useful for
Right-to-Left languages like Hebrew.
diff --git a/Documentation/user/instrument-notation.itely b/Documentation/user/instrument-notation.itely
index 3870835..59090fd 100644
--- a/Documentation/user/instrument-notation.itely
+++ b/Documentation/user/instrument-notation.itely
@@ -36,6 +36,7 @@ handle this cross-staffing behavior. In this section we discuss the
@menu
* Automatic staff changes::
* Manual staff switches::
+* Laissez vibrer ties::
* Pedals::
* Staff switch lines::
* Cross staff stems::
@@ -153,6 +154,28 @@ and the @context{Voice} is inserted afterwards
@end example
+@node Laissez vibrer ties
+@subsection Laissez vibrer ties
+@cindex Laissez vibrer
+@cindex Ties, laissez vibrer
+
+L.v. ties (laissez vibrer) indicate that notes must not be damped at the
+end. It is used in harp notation. They can be entered using
+@code{\laissezVibrer},
+
+@lilypond[fragment,raggedright,verbatim,relative=1]
+<c f g>\laissezVibrer
+@end lilypond
+
+@seealso
+
+Program reference:
+@internalsref{LaissezVibrerTie}
+@internalsref{LaissezVibrerTieColumn}
+
+Example files:
+@inputfileref{input/regression,laissez-vibrer-tie.ly}
+
@node Pedals
@subsection Pedals
@cindex Pedals
@@ -217,6 +240,10 @@ of the note head
c\sostenutoDown d e c, f g a\sostenutoUp
@end lilypond
+@seealso
+
+In this manual: @ref{Laissez vibrer ties}
+
@node Staff switch lines
@subsection Staff switch lines
diff --git a/THANKS b/THANKS
index 61b7139..763153a 100644
--- a/THANKS
+++ b/THANKS
@@ -22,6 +22,7 @@ Yoshinobu Ishizaki
SPONSORS
Aaron Mehl
+Henrik Frisk
Jay Hamilton
Jamie Bullock
D. Josiah Boothby
diff --git a/input/regression/laissez-vibrer-ties.ly b/input/regression/laissez-vibrer-ties.ly
new file mode 100644
index 0000000..b95c82d
--- /dev/null
+++ b/input/regression/laissez-vibrer-ties.ly
@@ -0,0 +1,31 @@
+
+\header {
+
+
+ texidoc = "
+l.v. ties should avoid dots and staff lines, similar to normal ties.
+They have fixed size. Their formatting can be tuned with
+@code{tie-configuration}.
+
+"
+ }
+
+\version "2.7.10"
+\paper {
+ raggedright = ##t
+}
+
+\relative {
+ <c e g>\laissezVibrer
+ <c f g>\laissezVibrer
+ <c d f g>\laissezVibrer
+ <c d f g>4.\laissezVibrer
+
+ <c d e f>4\laissezVibrer
+ \override LaissezVibrerTieColumn #'tie-configuration
+ = #'((-7 . -1)
+ (-5 . -1)
+ (-3 . 1)
+ (-1 . 1))
+ <c d e f>4\laissezVibrer
+}
diff --git a/lily/include/laissez-vibrer-tie-column.hh b/lily/include/laissez-vibrer-tie-column.hh
new file mode 100644
index 0000000..ea7b63c
--- /dev/null
+++ b/lily/include/laissez-vibrer-tie-column.hh
@@ -0,0 +1,24 @@
+/*
+ laissez-vibrer-tie-column.hh -- declare Laissez_vibrer_tie_column
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2005 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+*/
+
+#ifndef TIE_LAISSEZ_VIBRER_COLUMN_HH
+#define TIE_LAISSEZ_VIBRER_COLUMN_HH
+
+#include "grob-interface.hh"
+#include "lily-proto.hh"
+
+struct Laissez_vibrer_tie_column
+{
+ static bool has_interface (Grob *);
+ static void set_directions (Grob *me);
+};
+
+
+#endif /* TIE_LAISSEZ_VIBRER_COLUMN_HH */
+
diff --git a/lily/include/laissez-vibrer-tie.hh b/lily/include/laissez-vibrer-tie.hh
new file mode 100644
index 0000000..d500f08
--- /dev/null
+++ b/lily/include/laissez-vibrer-tie.hh
@@ -0,0 +1,28 @@
+/*
+ laissez-vibrer-tie.hh -- declare Laissez_vibrer_tie
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2005 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+*/
+
+#ifndef TIE_LAISSEZ_VIBRER_HH
+#define TIE_LAISSEZ_VIBRER_HH
+
+
+#include "grob-interface.hh"
+#include "lily-guile.hh"
+
+struct Laissez_vibrer_tie
+{
+ static bool has_interface (Grob *);
+
+ DECLARE_SCHEME_CALLBACK (print, (SCM));
+ static void set_direction (Grob *);
+ static int compare (Grob *const &s1,
+ Grob *const &s2);
+ static int get_position (Grob *);
+};
+
+#endif /* TIE_LAISSEZ_VIBRER_HH */
diff --git a/lily/include/lily-proto.hh b/lily/include/lily-proto.hh
index 05af750..1947a2b 100644
--- a/lily/include/lily-proto.hh
+++ b/lily/include/lily-proto.hh
@@ -144,6 +144,7 @@ class Simple_spacer;
class Simple_spacer_wrapper;
class Simultaneous_music;
class Simultaneous_music_iterator;
+class Skyline_entry;
class Slur_configuration;
class Slur_score_state;
class Span_score_bar_engraver;
@@ -157,6 +158,8 @@ class System;
class Tempo_performer;
class Tex_font_metric;
class Tie;
+class Tie_details;
+class Tie_configuration;
class Tie_performer;
class Time_scaled_music;
class Time_scaled_music_iterator;
diff --git a/lily/include/tie-column-format.hh b/lily/include/tie-column-format.hh
new file mode 100644
index 0000000..5f0c438
--- /dev/null
+++ b/lily/include/tie-column-format.hh
@@ -0,0 +1,39 @@
+/*
+ tie-column-format.hh -- declare
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2005 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+*/
+
+#ifndef TIE_COLUMN_FORMAT_HH
+#define TIE_COLUMN_FORMAT_HH
+
+
+
+void set_chord_outline (Array<Skyline_entry> *skyline,
+ Link_array<Item> bounds,
+ Grob *common,
+ Direction d);
+void set_tie_config_directions (Array<Tie_configuration> *tie_configs_ptr);
+void shift_small_ties (Array<Tie_configuration> *tie_configs,
+ Grob *staff_referencer,
+ Tie_details const &details);
+void final_shape_adjustment (Tie_configuration &conf,
+ Drul_array< Array<Skyline_entry> > const &skylines,
+ Grob *staff_referencer,
+ Tie_details const &details);
+void
+set_chord_outlines (Drul_array< Array<Skyline_entry> > *skyline_drul,
+ Link_array<Grob> ties,
+ Grob *common);
+
+void
+set_manual_tie_configuration (Array<Tie_configuration> *tie_configs,
+ bool *manual_override,
+ SCM manual_configs
+ );
+
+
+#endif /* TIE_COLUMN_FORMAT_HH */
diff --git a/lily/include/tie.hh b/lily/include/tie.hh
index 7327dbd..80501ac 100644
--- a/lily/include/tie.hh
+++ b/lily/include/tie.hh
@@ -75,9 +75,8 @@ public:
static int compare (Grob *const &s1,
Grob *const &s2);
- static
- Interval get_default_attachments (Spanner *me, Grob *common, Real gap,
- int *staff_position, bool *in_between);
+ static Interval get_default_attachments (Spanner *me, Grob *common, Real gap,
+ int *staff_position, bool *in_between);
};
diff --git a/lily/include/translator.icc b/lily/include/translator.icc
index 6895d68..5db338c 100644
--- a/lily/include/translator.icc
+++ b/lily/include/translator.icc
@@ -10,6 +10,7 @@
#define TRANSLATOR_ICC
#include "array.hh"
+#include "translator.hh"
/**
A macro to automate administration of translators.
diff --git a/lily/laissez-vibrer-engraver.cc b/lily/laissez-vibrer-engraver.cc
new file mode 100644
index 0000000..ef3d7a6
--- /dev/null
+++ b/lily/laissez-vibrer-engraver.cc
@@ -0,0 +1,86 @@
+/*
+ laissez-vibrer-engraver.cc -- implement Laissez_vibrer_engraver
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2005 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+*/
+
+
+#include "engraver.hh"
+#include "item.hh"
+#include "pointer-group-interface.hh"
+
+#include "translator.icc"
+
+class Laissez_vibrer_engraver : public Engraver
+{
+
+ Music *event_;
+ Grob *lv_column_;
+ Link_array<Grob> lv_ties_;
+
+ void stop_translation_timestep ();
+ DECLARE_ACKNOWLEDGER (note_head);
+
+ virtual bool try_music (Music *);
+public:
+ TRANSLATOR_DECLARATIONS (Laissez_vibrer_engraver);
+};
+
+Laissez_vibrer_engraver::Laissez_vibrer_engraver ()
+{
+ event_ = 0;
+ lv_column_ = 0;
+}
+
+void
+Laissez_vibrer_engraver::stop_translation_timestep ()
+{
+ event_ = 0;
+ lv_column_ = 0;
+ lv_ties_.clear ();
+}
+
+bool
+Laissez_vibrer_engraver::try_music (Music *m)
+{
+ event_ = m;
+ return true;
+}
+
+void
+Laissez_vibrer_engraver::acknowledge_note_head (Grob_info inf)
+{
+ if (!event_)
+ return;
+
+ if (!lv_column_)
+ {
+ lv_column_ = make_item ("LaissezVibrerTieColumn", event_->self_scm ());
+ }
+
+ Grob *lv_tie = make_item ("LaissezVibrerTie", event_->self_scm ());
+ lv_tie->set_object ("note-head", inf.grob ()->self_scm ());
+
+ Pointer_group_interface::add_grob (lv_column_, ly_symbol2scm ("ties"),
+ lv_tie);
+ lv_tie->set_parent (lv_column_, Y_AXIS);
+
+ lv_ties_.push (lv_tie);
+}
+
+
+
+ADD_ACKNOWLEDGER (Laissez_vibrer_engraver, note_head);
+ADD_TRANSLATOR (Laissez_vibrer_engraver,
+ /* doc */ "Create Laissez vibrer items.",
+
+ /* create */
+ "LaissezVibrerTie "
+ "LaissezVibrerTieColumn",
+
+ /* accept */ "laissez-vibrer-event",
+ /* read */ "",
+ /* write */ "");
diff --git a/lily/laissez-vibrer-tie-column.cc b/lily/laissez-vibrer-tie-column.cc
new file mode 100644
index 0000000..c381905
--- /dev/null
+++ b/lily/laissez-vibrer-tie-column.cc
@@ -0,0 +1,126 @@
+/*
+ laissez-vibrer-tie-column.cc -- implement Laissez_vibrer_tie_column
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2005 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+*/
+
+#include "laissez-vibrer-tie-column.hh"
+#include "laissez-vibrer-tie.hh"
+#include "grob.hh"
+#include "tie-column.hh"
+#include "tie.hh"
+#include "directional-element-interface.hh"
+#include "pointer-group-interface.hh"
+#include "staff-symbol-referencer.hh"
+#include "item.hh"
+#include "tie-column-format.hh"
+
+
+ADD_INTERFACE(Laissez_vibrer_tie_column,
+ "laissez-vibrer-tie-column-interface",
+ "The interface for a column of l.v. ties.",
+
+ /* properties */
+ "positioning-done"
+ "tie-configuration"
+ );
+
+
+
+/*
+ Cut & paste from tie-column.cc
+ */
+void
+Laissez_vibrer_tie_column::set_directions (Grob *me)
+{
+ if (!to_boolean (me->get_property ("positioning-done")))
+ me->set_property ("positioning-done", SCM_BOOL_T);
+ else
+ return;
+
+
+ extract_grob_set (me, "ties", lv_ro_ties);
+ Link_array<Grob> lv_ties (lv_ro_ties);
+
+ lv_ties.sort (&Laissez_vibrer_tie::compare);
+
+ Array<Tie_configuration> tie_configs;
+ Link_array<Item> heads;
+ for (int i = 0; i < lv_ties.size (); i++)
+ {
+ Tie_configuration conf;
+ conf.dir_ = get_grob_direction (lv_ties[i]);
+ Item *head = unsmob_item (lv_ties[i]->get_object ("note-head"));
+
+ heads.push (head);
+ if (head)
+ conf.position_ = (int) Staff_symbol_referencer::get_position (head);
+
+ tie_configs.push (conf);
+ }
+
+ bool manual_override = false;
+ SCM manual_configs = me->get_property ("tie-configuration");
+ set_manual_tie_configuration (&tie_configs,
+ &manual_override,
+ manual_configs
+ );
+
+ set_tie_config_directions (&tie_configs);
+
+ Grob *common = me;
+ for (int i = 0; i < lv_ties.size (); i++)
+ {
+ common = lv_ties[i]->common_refpoint (common, X_AXIS);
+ }
+
+ Drul_array< Array<Skyline_entry> > skylines;
+ set_chord_outline (&skylines[LEFT],
+ heads,
+ common, LEFT);
+
+ Real right_most = - infinity_f;
+ for (int i = 0; i < skylines[LEFT].size (); i++)
+ {
+ right_most = max (right_most, skylines[LEFT][i].height_);
+ }
+
+ Skyline_entry right_entry;
+ right_entry.width_.set_full ();
+ right_entry.height_ = right_most + 1.5;
+
+ skylines[RIGHT].push (right_entry);
+
+ Tie_details details;
+ details.init (lv_ties[0]);
+
+ /*
+ Calculate final width and shape of the ties.
+ */
+ for (int i = 0; i < lv_ties.size(); i++)
+ {
+ final_shape_adjustment (tie_configs[i],
+ skylines,
+ lv_ties[0],
+ details);
+ }
+
+ /*
+ Try to shift small ties into available spaces.
+ */
+ if (!manual_override)
+ {
+ shift_small_ties (&tie_configs, lv_ties[0], details);
+ }
+
+ for (int i = 0; i < lv_ties.size(); i++)
+ {
+ Tie::set_control_points (lv_ties[i], common, tie_configs[i],
+ details );
+ set_grob_direction (lv_ties[i], tie_configs[i].dir_);
+ }
+}
+
diff --git a/lily/laissez-vibrer-tie.cc b/lily/laissez-vibrer-tie.cc
new file mode 100644
index 0000000..c63f399
--- /dev/null
+++ b/lily/laissez-vibrer-tie.cc
@@ -0,0 +1,80 @@
+/*
+ laissez-vibrer-tie.cc -- implement Laissez_vibrer_tie
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2005 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+*/
+
+#include "laissez-vibrer-tie-column.hh"
+#include "laissez-vibrer-tie.hh"
+#include "directional-element-interface.hh"
+#include "grob.hh"
+#include "tie.hh"
+#include "warn.hh"
+#include "staff-symbol-referencer.hh"
+
+ADD_INTERFACE(Laissez_vibrer_tie,
+ "laissez-vibrer-tie-interface",
+ "The interface for l.v. tie items.",
+
+ /* properties */
+ "control-points "
+ "details "
+ "thickness "
+ "x-gap "
+ "details "
+ "note-head "
+ );
+
+MAKE_SCHEME_CALLBACK (Laissez_vibrer_tie, print, 1);
+SCM
+Laissez_vibrer_tie::print (SCM smob)
+{
+ Grob *me = unsmob_grob (smob);
+ if (CENTER == get_grob_direction (me))
+ set_direction (me);
+
+ if (!get_grob_direction (me))
+ me->programming_error ("lv. tie direction not set.");
+
+ SCM cp = me->get_property ("control-points");
+ if (!scm_is_pair (cp))
+ if (Laissez_vibrer_tie_column::has_interface (me->get_parent (Y_AXIS)))
+ {
+ Laissez_vibrer_tie_column::set_directions (me->get_parent (Y_AXIS));
+ }
+
+ return Tie::print (smob);
+}
+
+void
+Laissez_vibrer_tie::set_direction (Grob *me)
+{
+ if (!get_grob_direction (me))
+ {
+ if (Laissez_vibrer_tie_column::has_interface (me->get_parent (Y_AXIS)))
+ Laissez_vibrer_tie_column::set_directions (me->get_parent (Y_AXIS));
+ else
+ {
+ programming_error ("lv tie without Laissez_vibrer_tie_column");
+ set_grob_direction (me, UP);
+ }
+ }
+}
+
+int
+Laissez_vibrer_tie::get_position (Grob *me)
+{
+ Grob *h = unsmob_grob (me->get_object ("note-head"));
+ return (int) rint (Staff_symbol_referencer::get_position (h));
+}
+
+int
+Laissez_vibrer_tie::compare (Grob *const &s1,
+ Grob *const &s2)
+{
+ return sign (get_position (s1) - get_position (s2));
+}
+
diff --git a/lily/tie-column-format.cc b/lily/tie-column-format.cc
new file mode 100644
index 0000000..812782e
--- /dev/null
+++ b/lily/tie-column-format.cc
@@ -0,0 +1,284 @@
+/*
+ tie-column-format.cc -- implement formatting routines for Tie_column
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2005 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+*/
+
+#include "stem.hh"
+#include "note-head.hh"
+#include "tie.hh"
+#include "parray.hh"
+#include "spanner.hh"
+#include "item.hh"
+#include "staff-symbol-referencer.hh"
+
+#include <set>
+
+void
+set_manual_tie_configuration (Array<Tie_configuration> *tie_configs,
+ bool *manual_override,
+ SCM manual_configs
+ )
+{
+ *manual_override = false;
+ int k = 0;
+ for (SCM s = manual_configs;
+ scm_is_pair (s) && k < tie_configs->size(); s = scm_cdr (s))
+ {
+ SCM entry = scm_car (s);
+ if (!scm_is_pair (entry))
+ continue;
+
+ *manual_override = true;
+ Tie_configuration &conf = tie_configs->elem_ref (k);
+
+ Real complete_pos = robust_scm2double (scm_car (entry),
+ conf.position_);
+
+ conf.position_ = int (rint (complete_pos));
+ conf.delta_y_ = complete_pos - conf.position_;
+ conf.dir_ = Direction (robust_scm2int (scm_cdr (entry),
+ conf.dir_));
+ k ++;
+ }
+}
+
+void
+set_chord_outline (Array<Skyline_entry> *skyline,
+ Link_array<Item> bounds,
+ Grob *common,
+ Direction d)
+{
+ Real staff_space = Staff_symbol_referencer::staff_space (bounds[0]);
+
+ Array<Box> boxes;
+ Interval x_union;
+
+ Grob *stem = 0;
+ for (int i = 0; i < bounds.size (); i++)
+ {
+ Grob *head = bounds[i];
+ if (!Note_head::has_interface (head))
+ continue;
+
+ if (!stem)
+ stem = unsmob_grob (head->get_object ("stem"));
+
+ Real p = Staff_symbol_referencer::get_position (head);
+ Interval y ((p-1) * 0.5 * staff_space,
+ (p+1) * 0.5 * staff_space);
+
+ Interval x = head->extent (common, X_AXIS);
+ boxes.push (Box (x, y));
+ x_union.unite (x);
+ }
+
+ (*skyline) = empty_skyline (-d);
+
+ if (bounds[0]->break_status_dir ())
+ {
+ Real x = robust_relative_extent (bounds[0], common, X_AXIS)[-d];
+ skyline->elem_ref (0).height_ = x;
+ }
+
+ for (int i = 0; i < boxes.size (); i++)
+ insert_extent_into_skyline (skyline,
+ boxes[i], Y_AXIS, -d);
+ if (stem
+ && !Stem::is_invisible (stem))
+ {
+ Interval x;
+ x.add_point (stem->relative_coordinate (common, X_AXIS));
+ x.widen (staff_space / 20); // ugh.
+ Interval y;
+ y.add_point (Stem::stem_end_position (stem) * staff_space * .5);
+
+ Direction stemdir = Stem::get_direction (stem);
+ y.add_point (Stem::head_positions (stem)[-stemdir]
+ * staff_space * .5);
+
+ insert_extent_into_skyline (skyline, Box (x,y), Y_AXIS, -d);
+
+
+
+ if (d == LEFT)
+ {
+ Box flag_box = Stem::get_translated_flag (stem).extent_box ();
+ flag_box.translate( Offset (x[RIGHT], X_AXIS));
+ insert_extent_into_skyline (skyline, flag_box,
+ Y_AXIS, -d);
+ }
+ }
+
+ Direction updowndir = DOWN;
+ do
+ {
+ Interval x ;
+ Interval y;
+ if (boxes.size())
+ {
+ Box b = boxes.boundary (updowndir, 0);
+ x = b[X_AXIS];
+ x[-d] = b[X_AXIS].linear_combination (-d / 2);
+ y[-updowndir] = b[Y_AXIS][updowndir];
+ y[updowndir] = updowndir * infinity_f;
+ }
+
+ if (!x.is_empty ())
+ insert_extent_into_skyline (skyline,
+ Box (x,y),
+ Y_AXIS, -d);
+ }
+ while (flip (&updowndir) != DOWN);
+
+ for (int i = 0; i < bounds.size (); i++)
+ {
+ if (!Note_head::has_interface (bounds[i]))
+ continue;
+
+
+ Grob *dots = unsmob_grob (bounds[i]->get_object ("dot"));
+ if (dots && d == LEFT)
+ {
+ Interval x = dots->extent (common, X_AXIS);
+ Real p = Staff_symbol_referencer::get_position (dots);
+
+ Interval y (-1,1);
+ y *= (staff_space /4);
+ y.translate (p * staff_space * .5);
+
+ insert_extent_into_skyline (skyline,
+ Box (x,y), Y_AXIS, -d);
+ }
+ }
+}
+
+void
+set_chord_outlines (Drul_array< Array<Skyline_entry> > *skyline_drul,
+ Link_array<Grob> ties,
+ Grob *common)
+{
+ Direction d = LEFT;
+
+ do
+ {
+ Link_array<Item> bounds;
+
+ for (int i = 0; i < ties.size (); i++)
+ {
+ Item *it = dynamic_cast<Spanner*> (ties[i])->get_bound (d);
+
+ bounds.push (it);
+ }
+
+ set_chord_outline (&skyline_drul->elem_ref (d),
+ bounds, common, d);
+ }
+ while (flip (&d) != LEFT);
+}
+
+void
+shift_small_ties (Array<Tie_configuration> *tie_configs,
+ Grob *staff_referencer,
+ Tie_details const &details)
+{
+ set<int> positions_taken;
+ for (int i = 0; i < tie_configs->size (); i++)
+ positions_taken.insert (int (rint (tie_configs->elem (i).position_)));
+
+ for (int i = 0; i < tie_configs->size (); i++)
+ {
+ Tie_configuration * conf = &tie_configs->elem_ref (i);
+
+ /*
+ on staff line and small enough, translate a little further
+ */
+ Real h = conf->height (details);
+ bool next_free = positions_taken.find (int (rint (conf->position_ + conf->dir_)))
+ == positions_taken.end ();
+
+ int rounded_pos = int (rint (conf->position_ + conf->delta_y_ / details.staff_space_));
+ bool on_line = Staff_symbol_referencer::on_staffline (staff_referencer, rounded_pos);
+
+ if (next_free)
+ if (on_line && h < 0.4 * details.staff_space_)
+ {
+ positions_taken.insert (int (rint (conf->position_ + conf->dir_)));
+ conf->delta_y_ += 0.2 * details.staff_space_ * conf->dir_;
+ }
+ else if (!on_line && h > 0.6 * details.staff_space_)
+ {
+ positions_taken.insert (int (rint (conf->position_ + conf->dir_)));
+ conf->delta_y_ += 0.5 * details.staff_space_ * conf->dir_;
+ }
+ }
+}
+
+
+void
+final_shape_adjustment (Tie_configuration &conf,
+ Drul_array< Array<Skyline_entry> > const &skylines,
+ Grob *staff_referencer,
+ Tie_details const &details)
+{
+ Real line_dy = 0.0;
+ bool on_line = Staff_symbol_referencer::on_staffline (staff_referencer,
+ int (rint (conf.position_)));
+ if (on_line)
+ line_dy = - sign (conf.height (details) - 0.6 * details.staff_space_)
+ * 0.2 * details.staff_space_ * conf.dir_;
+
+ Real y = conf.position_ * details.staff_space_ * 0.5
+ + line_dy;
+
+ conf.attachment_x_ = get_skyline_attachment (skylines, y);
+ conf.attachment_x_.intersect (get_skyline_attachment (skylines,
+ y + conf.dir_ * details.staff_space_ * 0.5));
+
+ conf.delta_y_ += line_dy;
+ conf.attachment_x_.widen (-details.x_gap_);
+ if (!on_line
+ && Staff_symbol_referencer::staff_radius (staff_referencer) * details.staff_space_ > y)
+ conf.center_tie_vertically (details);
+}
+
+void
+set_tie_config_directions (Array<Tie_configuration> *tie_configs_ptr)
+{
+ Array<Tie_configuration> &tie_configs (*tie_configs_ptr);
+
+ if (!tie_configs[0].dir_)
+ tie_configs[0].dir_ = DOWN;
+ if (!tie_configs.top().dir_)
+ tie_configs.top().dir_ = UP;
+
+ /*
+ Seconds
+ */
+ for (int i = 1; i < tie_configs.size(); i++)
+ {
+ if (fabs (tie_configs[i-1].position_ - tie_configs[i].position_) <= 1)
+ {
+ if (!tie_configs[i-1].dir_)
+ tie_configs[i-1].dir_ = DOWN;
+ if (!tie_configs[i].dir_)
+ tie_configs[i].dir_ = UP;
+ }
+ }
+
+ for (int i = 1; i < tie_configs.size() - 1; i++)
+ {
+ if (tie_configs[i].dir_)
+ continue;
+
+ Direction position_dir = (Direction) sign (tie_configs[i].position_);
+ if (!position_dir)
+ position_dir = DOWN;
+
+ tie_configs[i].dir_ = position_dir;
+ }
+}
+
diff --git a/lily/tie-column.cc b/lily/tie-column.cc
index 70b2041..df6b7f1 100644
--- a/lily/tie-column.cc
+++ b/lily/tie-column.cc
@@ -10,19 +10,15 @@
#include <math.h>
#include <map>
-#include <set>
-#include "note-head.hh"
-#include "stem.hh"
#include "skyline.hh"
-#include "staff-symbol-referencer.hh"
#include "warn.hh"
#include "paper-column.hh"
#include "spanner.hh"
#include "pointer-group-interface.hh"
#include "tie.hh"
#include "directional-element-interface.hh"
-#include "rhythmic-head.hh"
+#include "tie-column-format.hh"
void
Tie_column::add_tie (Grob *me, Grob *tie)
@@ -52,12 +48,7 @@ Tie_column::set_directions (Grob *me)
}
}
-int
-Tie::compare (Grob *const &s1,
- Grob *const &s2)
-{
- return sign (Tie::get_position (s1) - Tie::get_position (s2));
-}
+
MAKE_SCHEME_CALLBACK (Tie_column, after_line_breaking, 1);
SCM
@@ -92,243 +83,6 @@ Tie_column::before_line_breaking (SCM smob)
void
-set_chord_outline (Array<Skyline_entry> *skyline,
- Link_array<Item> bounds,
- Grob *common,
- Direction d)
-{
- Real staff_space = Staff_symbol_referencer::staff_space (bounds[0]);
-
- Array<Box> boxes;
- Interval x_union;
-
- Grob *stem = 0;
- for (int i = 0; i < bounds.size (); i++)
- {
- Grob *head = bounds[i];
- if (!Note_head::has_interface (head))
- continue;
-
- if (!stem)
- stem = unsmob_grob (head->get_object ("stem"));
-
- Real p = Staff_symbol_referencer::get_position (head);
- Interval y ((p-1) * 0.5 * staff_space,
- (p+1) * 0.5 * staff_space);
-
- Interval x = head->extent (common, X_AXIS);
- boxes.push (Box (x, y));
- x_union.unite (x);
- }
-
- (*skyline) = empty_skyline (-d);
-
- if (bounds[0]->break_status_dir ())
- {
- Real x = robust_relative_extent (bounds[0], common, X_AXIS)[-d];
- skyline->elem_ref (0).height_ = x;
- }
-
- for (int i = 0; i < boxes.size (); i++)
- insert_extent_into_skyline (skyline,
- boxes[i], Y_AXIS, -d);
- if (stem
- && !Stem::is_invisible (stem))
- {
- Interval x;
- x.add_point (stem->relative_coordinate (common, X_AXIS));
- x.widen (staff_space / 20); // ugh.
- Interval y;
- y.add_point (Stem::stem_end_position (stem) * staff_space * .5);
-
- Direction stemdir = Stem::get_direction (stem);
- y.add_point (Stem::head_positions (stem)[-stemdir]
- * staff_space * .5);
-
- insert_extent_into_skyline (skyline, Box (x,y), Y_AXIS, -d);
-
-
-
- if (d == LEFT)
- {
- Box flag_box = Stem::get_translated_flag (stem).extent_box ();
- flag_box.translate( Offset (x[RIGHT], X_AXIS));
- insert_extent_into_skyline (skyline, flag_box,
- Y_AXIS, -d);
- }
- }
-
- Direction updowndir = DOWN;
- do
- {
- Interval x ;
- Interval y;
- if (boxes.size())
- {
- Box b = boxes.boundary (updowndir, 0);
- x = b[X_AXIS];
- x[-d] = b[X_AXIS].linear_combination (-d / 2);
- y[-updowndir] = b[Y_AXIS][updowndir];
- y[updowndir] = updowndir * infinity_f;
- }
-
- if (!x.is_empty ())
- insert_extent_into_skyline (skyline,
- Box (x,y),
- Y_AXIS, -d);
- }
- while (flip (&updowndir) != DOWN);
-
- for (int i = 0; i < bounds.size (); i++)
- {
- if (!Note_head::has_interface (bounds[i]))
- continue;
-
-
- Grob *dots = unsmob_grob (bounds[i]->get_object ("dot"));
- if (dots && d == LEFT)
- {
- Interval x = dots->extent (common, X_AXIS);
- Real p = Staff_symbol_referencer::get_position (dots);
-
- Interval y (-1,1);
- y *= (staff_space /4);
- y.translate (p * staff_space * .5);
-
- insert_extent_into_skyline (skyline,
- Box (x,y), Y_AXIS, -d);
- }
- }
-}
-
-void
-set_chord_outlines (Drul_array< Array<Skyline_entry> > *skyline_drul,
- Link_array<Grob> ties,
- Grob *common)
-{
- Direction d = LEFT;
-
- do
- {
- Link_array<Item> bounds;
-
- for (int i = 0; i < ties.size (); i++)
- {
- Item *it = dynamic_cast<Spanner*> (ties[i])->get_bound (d);
-
- bounds.push (it);
- }
-
- set_chord_outline (&skyline_drul->elem_ref (d),
- bounds, common, d);
- }
- while (flip (&d) != LEFT);
-}
-
-void
-shift_small_ties (Array<Tie_configuration> *tie_configs,
- Grob *staff_referencer,
- Tie_details const &details)
-{
- set<int> positions_taken;
- for (int i = 0; i < tie_configs->size (); i++)
- positions_taken.insert (int (rint (tie_configs->elem (i).position_)));
-
- for (int i = 0; i < tie_configs->size (); i++)
- {
- Tie_configuration * conf = &tie_configs->elem_ref (i);
-
- /*
- on staff line and small enough, translate a little further
- */
- Real h = conf->height (details);
- bool next_free = positions_taken.find (int (rint (conf->position_ + conf->dir_)))
- == positions_taken.end ();
-
- int rounded_pos = int (rint (conf->position_ + conf->delta_y_ / details.staff_space_));
- bool on_line = Staff_symbol_referencer::on_staffline (staff_referencer, rounded_pos);
-
- if (next_free)
- if (on_line && h < 0.4 * details.staff_space_)
- {
- positions_taken.insert (int (rint (conf->position_ + conf->dir_)));
- conf->delta_y_ += 0.2 * details.staff_space_ * conf->dir_;
- }
- else if (!on_line && h > 0.6 * details.staff_space_)
- {
- positions_taken.insert (int (rint (conf->position_ + conf->dir_)));
- conf->delta_y_ += 0.5 * details.staff_space_ * conf->dir_;
- }
- }
-}
-
-
-void
-final_shape_adjustment (Tie_configuration &conf,
- Drul_array< Array<Skyline_entry> > const &skylines,
- Grob *staff_referencer,
- Tie_details const &details)
-{
- Real line_dy = 0.0;
- bool on_line = Staff_symbol_referencer::on_staffline (staff_referencer,
- int (rint (conf.position_)));
- if (on_line)
- line_dy = - sign (conf.height (details) - 0.6 * details.staff_space_)
- * 0.2 * details.staff_space_ * conf.dir_;
-
- Real y = conf.position_ * details.staff_space_ * 0.5
- + line_dy;
-
- conf.attachment_x_ = get_skyline_attachment (skylines, y);
- conf.attachment_x_.intersect (get_skyline_attachment (skylines,
- y + conf.dir_ * details.staff_space_ * 0.5));
-
- conf.delta_y_ += line_dy;
- conf.attachment_x_.widen (-details.x_gap_);
- if (!on_line
- && Staff_symbol_referencer::staff_radius (staff_referencer) * details.staff_space_ > y)
- conf.center_tie_vertically (details);
-}
-
-void
-set_tie_config_directions (Array<Tie_configuration> *tie_configs_ptr)
-{
- Array<Tie_configuration> &tie_configs (*tie_configs_ptr);
-
- if (!tie_configs[0].dir_)
- tie_configs[0].dir_ = DOWN;
- if (!tie_configs.top().dir_)
- tie_configs.top().dir_ = UP;
-
- /*
- Seconds
- */
- for (int i = 1; i < tie_configs.size(); i++)
- {
- if (fabs (tie_configs[i-1].position_ - tie_configs[i].position_) <= 1)
- {
- if (!tie_configs[i-1].dir_)
- tie_configs[i-1].dir_ = DOWN;
- if (!tie_configs[i].dir_)
- tie_configs[i].dir_ = UP;
- }
- }
-
- for (int i = 1; i < tie_configs.size() - 1; i++)
- {
- if (tie_configs[i].dir_)
- continue;
-
- Direction position_dir = (Direction) sign (tie_configs[i].position_);
- if (!position_dir)
- position_dir = DOWN;
-
- tie_configs[i].dir_ = position_dir;
- }
-}
-
-
-void
Tie_column::new_directions (Grob *me)
{
extract_grob_set (me, "ties", ro_ties);
@@ -355,23 +109,9 @@ Tie_column::new_directions (Grob *me)
SCM manual_configs = me->get_property ("tie-configuration");
bool manual_override = false;
- int k = 0;
- for (SCM s = manual_configs;
- scm_is_pair (s) && k < tie_configs.size(); s = scm_cdr (s))
- {
- SCM entry = scm_car (s);
- if (!scm_is_pair (entry))
- continue;
-
- manual_override = true;
- Real complete_pos = robust_scm2double (scm_car (entry), tie_configs[k].position_);
-
- tie_configs[k].position_ = int (rint (complete_pos));
- tie_configs[k].delta_y_ = complete_pos - tie_configs[k].position_;
- tie_configs[k].dir_ = Direction (robust_scm2int (scm_cdr (entry), tie_configs[k].dir_));
- k ++;
- }
-
+ set_manual_tie_configuration (&tie_configs,
+ &manual_override,
+ manual_configs);
set_tie_config_directions (&tie_configs);
Grob *common = me;
@@ -438,6 +178,7 @@ Tie_column::new_directions (Grob *me)
}
+
ADD_INTERFACE (Tie_column, "tie-column-interface",
"Object that sets directions of multiple ties in a tied chord",
@@ -445,3 +186,4 @@ ADD_INTERFACE (Tie_column, "tie-column-interface",
"positioning-done "
"tie-configuration "
);
+
diff --git a/lily/tie.cc b/lily/tie.cc
index 8c812e8..cf2c4d5 100644
--- a/lily/tie.cc
+++ b/lily/tie.cc
@@ -24,17 +24,12 @@
#include "note-head.hh"
#include "tie-column.hh"
-/*
- tie: Connect two noteheads.
-
- What if we have
-
- c4 ~ \clef bass ; c4 or
-
- c4 \staffchange c4
-
- do we have non-horizontal ties then?
-*/
+int
+Tie::compare (Grob *const &s1,
+ Grob *const &s2)
+{
+ return sign (Tie::get_position (s1) - Tie::get_position (s2));
+}
void
Tie::set_head (Grob *me, Direction d, Grob *h)
diff --git a/ly/declarations-init.ly b/ly/declarations-init.ly
index 824f0ef..60e8fba 100644
--- a/ly/declarations-init.ly
+++ b/ly/declarations-init.ly
@@ -65,7 +65,8 @@ escapedSmallerSymbol = #(make-span-event 'CrescendoEvent START)
melisma = #(make-span-event 'ManualMelismaEvent START)
melismaEnd = #(make-span-event 'ManualMelismaEvent STOP)
-
+laissezVibrer = #(make-music 'LaissezVibrerEvent)
+
\include "grace-init.ly"
\include "midi-init.ly"
\include "paper-defaults.ly"
diff --git a/ly/engraver-init.ly b/ly/engraver-init.ly
index 15e40fc..6bd5df4 100644
--- a/ly/engraver-init.ly
+++ b/ly/engraver-init.ly
@@ -182,7 +182,7 @@ contained staves are not connected vertically."
\consists "Trill_spanner_engraver"
\consists "Grob_pq_engraver"
\consists "Forbid_line_break_engraver"
-
+ \consists "Laissez_vibrer_engraver"
\consists "Note_head_line_engraver"
\consists "Glissando_engraver"
\consists "Ligature_bracket_engraver"
diff --git a/mf/GNUmakefile b/mf/GNUmakefile
index f8b18ab..bef84b3 100644
--- a/mf/GNUmakefile
+++ b/mf/GNUmakefile
@@ -43,7 +43,7 @@ $(outdir)/aybabtu.otf-gtable: $(BRACES:%=$(outdir)/feta-braces-%.otf-gtable)
LOG_FILES = $(FETA_MF_FILES:%.mf=$(outdir)/%.log)
LISP_FILES = $(FETA_MF_FILES:%.mf=$(outdir)/%.lisp)
TEXTABLES = $(FETA_MF_FILES:%.mf=$(outdir)/%.tex)
-ENC_FILES = $(TEXTABLES:.tex=.enc) $(outdir)/cmr.enc
+ENC_FILES = $(TEXTABLES:.tex=.enc)
TFM_FILES = $(FETA_MF_FILES:%.mf=$(outdir)/%.tfm)\
$(SAUTER_FONTS:%=$(outdir)/%.tfm)
FETA_LIST_FILES = $(FETA_MF_FILES:%.mf=$(outdir)/%list.ly)
diff --git a/mf/cmr.enc.in b/mf/cmr.enc.in
deleted file mode 100644
index fca576b..0000000
--- a/mf/cmr.enc.in
+++ /dev/null
@@ -1,36 +0,0 @@
-% Thomas Esser, Dec 2002. public domain
-%
-% Encoding for:
-% cmb10 cmbx10 cmbx12 cmbx5 cmbx6 cmbx7 cmbx8 cmbx9 cmbxsl10
-% cmdunh10 cmr10 cmr12 cmr17cmr6 cmr7 cmr8 cmr9 cmsl10 cmsl12 cmsl8
-% cmsl9 cmss10cmss12 cmss17 cmss8 cmss9 cmssbx10 cmssdc10 cmssi10
-% cmssi12 cmssi17 cmssi8cmssi9 cmssq8 cmssqi8 cmvtt10
-%
-/TeXf7b6d320Encoding [
-/Gamma /Delta /Theta /Lambda /Xi /Pi /Sigma /Upsilon /Phi /Psi /Omega
-/ff /fi /fl /ffi /ffl /dotlessi /dotlessj /grave /acute /caron /breve
-/macron /ring /cedilla /germandbls /ae /oe /oslash /AE /OE /Oslash
-/suppress /exclam /quotedblright /numbersign /dollar /percent /ampersand
-/quoteright /parenleft /parenright /asterisk /plus /comma /hyphen
-/period /slash /zero /one /two /three /four /five /six /seven /eight
-/nine /colon /semicolon /exclamdown /equal /questiondown /question /at
-/A /B /C /D /E /F /G /H /I /J /K /L /M /N /O /P /Q /R /S /T /U /V /W /X
-/Y /Z /bracketleft /quotedblleft /bracketright /circumflex /dotaccent
-/quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o /p /q /r /s /t /u
-/v /w /x /y /z /endash /emdash /hungarumlaut /tilde /dieresis /suppress
-/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /space
-/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
-] def
diff --git a/scm/define-grobs.scm b/scm/define-grobs.scm
index fd98427..993cff0 100644
--- a/scm/define-grobs.scm
+++ b/scm/define-grobs.scm
@@ -677,6 +677,26 @@
(interfaces . (key-signature-interface
font-interface
break-aligned-interface))))))
+ (LaissezVibrerTie
+ . (
+ (print-function . ,Laissez_vibrer_tie::print)
+ (details . ((ratio . 0.333)
+ (height-limit . 1.0)))
+ (thickness . 1.0)
+ (meta . ((class . Item)
+ (interfaces . (laissez-vibrer-tie-interface))
+ ))
+ ))
+
+ (LaissezVibrerTieColumn
+ . (
+ (X-extent-callback . #f)
+ (Y-extent-callback . #f)
+ (meta . ((class . Item)
+ (interfaces . (laissez-vibrer-tie-column-interface))
+ ))
+ ))
+
(LedgerLineSpanner
. (
(print-function . ,Ledger_line_spanner::print)
diff --git a/scm/define-music-types.scm b/scm/define-music-types.scm
index 1bdead9..3c9d9e2 100644
--- a/scm/define-music-types.scm
+++ b/scm/define-music-types.scm
@@ -221,7 +221,13 @@ Syntax: @code{\\key } @var{name} @var{scale}.")
(to-relative-callback . ,(lambda (x p) p))
(types . (general-music key-change-event event))
))
-
+ (LaissezVibrerEvent
+ . ((description . "Don't damp this chord.
+
+Syntax: @var{note}\\laissezVibrer.")
+
+ (types . (general-music event laissez-vibrer-event))
+ ))
(LigatureEvent
. (
(description . "(docme).")