From: Han-Wen Nienhuys Date: Mon, 12 Sep 2005 12:20:26 +0000 (+0000) Subject: * Documentation/user/instrument-notation.itely (Laissez vibrer X-Git-Tag: release/2.7.10~8 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=4bee689d7993ecf9af95d33c7f8f4ecd8d74a3cc;p=lilypond.git * 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. --- diff --git a/ChangeLog b/ChangeLog index 4480150265..4061db9478 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,42 @@ +2005-09-12 Han-Wen Nienhuys + + * 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 * Documentation/user/examples.itely: typo fix. Thanks, Matevž diff --git a/Documentation/topdocs/NEWS.tely b/Documentation/topdocs/NEWS.tely index 424d593500..03c191c2a1 100644 --- a/Documentation/topdocs/NEWS.tely +++ b/Documentation/topdocs/NEWS.tely @@ -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] + \laissezVibrer \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 diff --git a/Documentation/user/instrument-notation.itely b/Documentation/user/instrument-notation.itely index 38708358b3..59090fdaae 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] +\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 61b7139e4f..763153aebe 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 0000000000..b95c82d846 --- /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 { + \laissezVibrer + \laissezVibrer + \laissezVibrer + 4.\laissezVibrer + + 4\laissezVibrer + \override LaissezVibrerTieColumn #'tie-configuration + = #'((-7 . -1) + (-5 . -1) + (-3 . 1) + (-1 . 1)) + 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 0000000000..ea7b63c5cd --- /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 + +*/ + +#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 0000000000..d500f08f0c --- /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 + +*/ + +#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 05af750dbf..1947a2b220 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 0000000000..5f0c438e68 --- /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 + +*/ + +#ifndef TIE_COLUMN_FORMAT_HH +#define TIE_COLUMN_FORMAT_HH + + + +void set_chord_outline (Array *skyline, + Link_array bounds, + Grob *common, + Direction d); +void set_tie_config_directions (Array *tie_configs_ptr); +void shift_small_ties (Array *tie_configs, + Grob *staff_referencer, + Tie_details const &details); +void final_shape_adjustment (Tie_configuration &conf, + Drul_array< Array > const &skylines, + Grob *staff_referencer, + Tie_details const &details); +void +set_chord_outlines (Drul_array< Array > *skyline_drul, + Link_array ties, + Grob *common); + +void +set_manual_tie_configuration (Array *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 7327dbd4c4..80501acf30 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 6895d6890b..5db338c515 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 0000000000..ef3d7a6b7b --- /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 + +*/ + + +#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 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 0000000000..c381905719 --- /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 + +*/ + +#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 lv_ties (lv_ro_ties); + + lv_ties.sort (&Laissez_vibrer_tie::compare); + + Array tie_configs; + Link_array 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 > 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 0000000000..c63f3990e1 --- /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 + +*/ + +#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 0000000000..812782ef4e --- /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 + +*/ + +#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 + +void +set_manual_tie_configuration (Array *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, + Link_array bounds, + Grob *common, + Direction d) +{ + Real staff_space = Staff_symbol_referencer::staff_space (bounds[0]); + + Array 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_drul, + Link_array ties, + Grob *common) +{ + Direction d = LEFT; + + do + { + Link_array bounds; + + for (int i = 0; i < ties.size (); i++) + { + Item *it = dynamic_cast (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_configs, + Grob *staff_referencer, + Tie_details const &details) +{ + set 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 > 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_configs_ptr) +{ + Array &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 70b2041067..df6b7f18c8 100644 --- a/lily/tie-column.cc +++ b/lily/tie-column.cc @@ -10,19 +10,15 @@ #include #include -#include -#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, - Link_array bounds, - Grob *common, - Direction d) -{ - Real staff_space = Staff_symbol_referencer::staff_space (bounds[0]); - - Array 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_drul, - Link_array ties, - Grob *common) -{ - Direction d = LEFT; - - do - { - Link_array bounds; - - for (int i = 0; i < ties.size (); i++) - { - Item *it = dynamic_cast (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_configs, - Grob *staff_referencer, - Tie_details const &details) -{ - set 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 > 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_configs_ptr) -{ - Array &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 " ); + diff --git a/lily/tie.cc b/lily/tie.cc index 8c812e811e..cf2c4d5a38 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 824f0ef6fd..60e8fbabe0 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 15e40fc446..6bd5df4365 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 f8b18ab47c..bef84b3a59 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 fca576b7b4..0000000000 --- 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 fd984274e5..993cff018e 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 1bdead9056..3c9d9e2b65 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).")