]> git.donarmstrong.com Git - lilypond.git/commitdiff
* Documentation/user/instrument-notation.itely (Laissez vibrer
authorHan-Wen Nienhuys <hanwen@xs4all.nl>
Mon, 12 Sep 2005 12:20:26 +0000 (12:20 +0000)
committerHan-Wen Nienhuys <hanwen@xs4all.nl>
Mon, 12 Sep 2005 12:20:26 +0000 (12:20 +0000)
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.

23 files changed:
ChangeLog
Documentation/topdocs/NEWS.tely
Documentation/user/instrument-notation.itely
THANKS
input/regression/laissez-vibrer-ties.ly [new file with mode: 0644]
lily/include/laissez-vibrer-tie-column.hh [new file with mode: 0644]
lily/include/laissez-vibrer-tie.hh [new file with mode: 0644]
lily/include/lily-proto.hh
lily/include/tie-column-format.hh [new file with mode: 0644]
lily/include/tie.hh
lily/include/translator.icc
lily/laissez-vibrer-engraver.cc [new file with mode: 0644]
lily/laissez-vibrer-tie-column.cc [new file with mode: 0644]
lily/laissez-vibrer-tie.cc [new file with mode: 0644]
lily/tie-column-format.cc [new file with mode: 0644]
lily/tie-column.cc
lily/tie.cc
ly/declarations-init.ly
ly/engraver-init.ly
mf/GNUmakefile
mf/cmr.enc.in [deleted file]
scm/define-grobs.scm
scm/define-music-types.scm

index 4480150265bdb6b915841e3ce3c46caea112295c..4061db947874c628e48c0e88edd23bdce5e31411 100644 (file)
--- 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ž
index 424d5935007b25eb61e94b057e1b688f762243b3..03c191c2a1d139bc754693a00c13aa9b07fc9bb0 100644 (file)
@@ -46,6 +46,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
index 38708358b33af47761122d19b0ca68133c8b60aa..59090fdaae6479ce1e5f45e5924bf63fc3b6dc4c 100644 (file)
@@ -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 61b7139e4f9a37698205926b5415522a455d195c..763153aebe6f512a47c58d3d7b5cd3009b1a6749 100644 (file)
--- 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 (file)
index 0000000..b95c82d
--- /dev/null
@@ -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 (file)
index 0000000..ea7b63c
--- /dev/null
@@ -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 (file)
index 0000000..d500f08
--- /dev/null
@@ -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 */
index 05af750dbfb9b23bf3094416c904b2e349ac92c6..1947a2b2209a1cbacff3f3204ce4e71f1a528208 100644 (file)
@@ -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 (file)
index 0000000..5f0c438
--- /dev/null
@@ -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 */
index 7327dbd4c4733d9cdefaf2b07ce9b3a5358d5cea..80501acf30502737c6d5a114634ea628139603d3 100644 (file)
@@ -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);
   
 };
 
index 6895d6890b2f92375b22033dad27762349c4146b..5db338c5154dd8f9b412312d016a9b68b7db5326 100644 (file)
@@ -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 (file)
index 0000000..ef3d7a6
--- /dev/null
@@ -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 (file)
index 0000000..c381905
--- /dev/null
@@ -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 (file)
index 0000000..c63f399
--- /dev/null
@@ -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 (file)
index 0000000..812782e
--- /dev/null
@@ -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;
+    }
+}
+                          
index 70b2041067cb9ca44ff5bb10e2e7f5a3329d7e0c..df6b7f18c8c893d283cdcb51632841da3fd995f9 100644 (file)
 
 #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
@@ -91,243 +82,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)
 {
@@ -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 "
               );
+
index 8c812e811e9074226c40e6980f8b0a0564ee7a5b..cf2c4d5a389f3c73e292690ca2d23f9d27ac2064 100644 (file)
 #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)
index 824f0ef6fd635905e4e32c4754f44467c11fc1c5..60e8fbabe0cf6109d36fa7ea4d3d5fcffe833f9c 100644 (file)
@@ -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"
index 15e40fc446c928c8354fe329ab29ceb2a53ef3a4..6bd5df4365583d0c8224d288bd4307ebe008f3ae 100644 (file)
@@ -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"
index f8b18ab47cfeb4353c1022bbaaf69dd931fd5416..bef84b3a59f4fe118f8391b9e13e4c544ad4490f 100644 (file)
@@ -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 (file)
index fca576b..0000000
+++ /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
index fd984274e54252b61fc76f1320d51e31c9dfe8ca..993cff018e6e705e50918dfdccfa2ddb5433783a 100644 (file)
                 (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)
index 1bdead905637a2d8cfa43f0c8bb6a24f79938837..3c9d9e2b65527a63267f25a85dfe1d858d2e7d3b 100644 (file)
@@ -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).")