diff options
author | Mike Solomon <mike@apollinemike.com> | 2011-04-28 09:10:27 -0400 |
---|---|---|
committer | Carl Sorensen <c_sorensen@byu.edu> | 2011-05-25 11:54:34 -0600 |
commit | d623a43831b22eb89f75b9b8517a7f38d02cb7d4 (patch) | |
tree | 68644e75d5cc5da7d91da3b499337b26b629550e | |
parent | f6aa099ed44aa739bce92d5a5af7543a62ff06ec (diff) |
Allows for individual glissandi between members of NoteColumns.
The property glissandoMap is used to tell the glissando-engraver
what note-column members to connect via glissandi.
-rw-r--r-- | input/regression/glissando-chord.ly | 23 | ||||
-rw-r--r-- | lily/glissando-engraver.cc | 98 | ||||
-rw-r--r-- | scm/define-context-properties.scm | 5 | ||||
-rw-r--r-- | scm/define-grob-interfaces.scm | 2 | ||||
-rw-r--r-- | scm/define-grob-properties.scm | 2 |
5 files changed, 105 insertions, 25 deletions
diff --git a/input/regression/glissando-chord.ly b/input/regression/glissando-chord.ly new file mode 100644 index 0000000000..e140c38d8e --- /dev/null +++ b/input/regression/glissando-chord.ly @@ -0,0 +1,23 @@ +\version "2.15.0" + +\header { + texidoc = "LilyPond typesets glissandi between chords." +} + +\relative c' { + c1 \glissando g' + c,1 \glissando s1 g' + <c, e>1 \glissando <g' b> + <c, e>1 \glissando s1 <g' b> + \set glissandoMap = #'((0 . 1) (1 . 0)) + <c, g'>1 \glissando s1 <d a'> + \set glissandoMap = #'((0 . 0) (0 . 1) (0 . 2)) + c1 \glissando s1 <d f a> + \set glissandoMap = #'((2 . 0) (1 . 0) (0 . 0)) + <d f a>1 \glissando s1 c + \unset glissandoMap + \once \override Voice . Glissando #'style = + #(lambda (grob) + (if (eq? 1 (ly:grob-property grob 'glissando-index)) 'zigzag 'default)) + <d f a>1 \glissando s1 <f a c> +} diff --git a/lily/glissando-engraver.cc b/lily/glissando-engraver.cc index 99eb6bc515..08f420c128 100644 --- a/lily/glissando-engraver.cc +++ b/lily/glissando-engraver.cc @@ -20,6 +20,7 @@ #include "engraver.hh" #include "international.hh" +#include "pointer-group-interface.hh" #include "rhythmic-head.hh" #include "spanner.hh" #include "stream-event.hh" @@ -35,21 +36,29 @@ public: protected: DECLARE_TRANSLATOR_LISTENER (glissando); - DECLARE_ACKNOWLEDGER (rhythmic_head); + DECLARE_ACKNOWLEDGER (note_column); virtual void finalize (); void stop_translation_timestep (); void process_music (); + private: - Spanner *line_; - Spanner *last_line_; + vector<Spanner *> lines_; + bool start_glissandi; + bool stop_glissandi; + Stream_event *event_; + SCM map; + vector<vsize> note_column_1; + vector<vsize> note_column_2; }; Glissando_engraver::Glissando_engraver () { - last_line_ = line_ = 0; event_ = 0; + map = SCM_EOL; + start_glissandi = false; + stop_glissandi = false; } IMPLEMENT_TRANSLATOR_LISTENER (Glissando_engraver, glissando); @@ -63,44 +72,85 @@ void Glissando_engraver::process_music () { if (event_) - line_ = make_spanner ("Glissando", event_->self_scm ()); + start_glissandi = true; } void -Glissando_engraver::acknowledge_rhythmic_head (Grob_info info) +Glissando_engraver::acknowledge_note_column (Grob_info info) { Grob *g = info.grob (); - if (line_) - line_->set_bound (LEFT, g); + if (start_glissandi) + { + extract_grob_set (g, "note-heads", note_heads); + map = get_property ("glissandoMap"); + if (map == SCM_EOL) + for (vsize i = 0; i < note_heads.size (); i++) + { + note_column_1.push_back (i); + note_column_2.push_back (i); + } + else + for (SCM m = map; scm_is_pair (m); m = scm_cdr (m)) + { + SCM candidate = scm_car (m); + if (!scm_is_pair (candidate)) + continue; + int n1 = robust_scm2int (scm_car (candidate), -1); + int n2 = robust_scm2int (scm_cdr (candidate), -1); + if (n1 < 0 || n2 < 0 || n1 >= note_heads.size ()) + continue; + note_column_1.push_back (vsize (n1)); + note_column_2.push_back (vsize (n2)); + } + for (vsize i=0; i < note_column_1.size (); i++) + { + lines_.push_back (make_spanner ("Glissando", event_->self_scm ())); + lines_.back ()->set_bound (LEFT, note_heads[note_column_1[i]]); + } + } - if (last_line_) + if (stop_glissandi) { - last_line_->set_bound (RIGHT, g); - announce_end_grob (last_line_, g->self_scm ()); + extract_grob_set (g, "note-heads", note_heads); + int glissando_index = 0; + for (vsize i=0; i < note_column_1.size (); i++) + { + if (note_column_2[i] >= note_heads.size ()) + lines_[i]->suicide (); + else + { + lines_[i]->set_bound (RIGHT, note_heads[note_column_2[i]]); + lines_[i]->set_property ("glissando-index", scm_from_int (glissando_index)); + glissando_index++; + announce_end_grob (lines_[i], note_heads[note_column_2[i]]->self_scm ()); + } + } + lines_.clear (); + note_column_1.clear (); + note_column_2.clear (); + stop_glissandi = false; } } void Glissando_engraver::stop_translation_timestep () { - if (last_line_ && last_line_->get_bound (RIGHT)) - { - last_line_ = 0; - } - if (line_) + + if (start_glissandi) { - if (last_line_) + if (stop_glissandi) programming_error ("overwriting glissando"); - last_line_ = line_; + stop_glissandi = true; } - line_ = 0; + + start_glissandi = false; event_ = 0; } void Glissando_engraver::finalize () { - if (line_) + if (!lines_.empty ()) { string msg = _ ("unterminated glissando"); @@ -109,12 +159,12 @@ Glissando_engraver::finalize () else warning (msg); - line_->suicide (); - line_ = 0; + for (vsize i=0; i < lines_.size (); i++) + lines_[i]->suicide (); } } -ADD_ACKNOWLEDGER (Glissando_engraver, rhythmic_head); +ADD_ACKNOWLEDGER (Glissando_engraver, note_column); ADD_TRANSLATOR (Glissando_engraver, /* doc */ "Engrave glissandi.", @@ -123,7 +173,7 @@ ADD_TRANSLATOR (Glissando_engraver, "Glissando ", /* read */ - "", + "glissandoMap ", /* write */ "" diff --git a/scm/define-context-properties.scm b/scm/define-context-properties.scm index a813f1421f..e9484ba194 100644 --- a/scm/define-context-properties.scm +++ b/scm/define-context-properties.scm @@ -257,6 +257,11 @@ containing, in the correct order, the labels to be used for lettered frets in tablature.") + (glissandoMap ,list? "A map in the form of '((source1 . target1) +(source2 . target2) (sourcen . targetn)) showing the glissandi to +be drawn for note columns. The value '() will default to '((0 . 0) +(1 . 1) (n . n)), where n is the minimal number of note-heads in +the two note columns between which the glissandi occur.") (gridInterval ,ly:moment? "Interval for which to generate @code{GridPoint}s.") diff --git a/scm/define-grob-interfaces.scm b/scm/define-grob-interfaces.scm index edc02a7fb3..a7090de032 100644 --- a/scm/define-grob-interfaces.scm +++ b/scm/define-grob-interfaces.scm @@ -100,7 +100,7 @@ note)." (ly:add-interface 'glissando-interface "A glissando." - '()) + '(glissando-index)) (ly:add-interface 'grace-spacing-interface diff --git a/scm/define-grob-properties.scm b/scm/define-grob-properties.scm index 3381cb9e27..7fd0b13819 100644 --- a/scm/define-grob-properties.scm +++ b/scm/define-grob-properties.scm @@ -1003,6 +1003,8 @@ in addition to notes and stems.") (figures ,ly:grob-array? "Figured bass objects for continuation line.") + (glissando-index ,integer? "The index of a glissando in its note +column.") (grace-spacing ,ly:grob? "A run of grace notes.") (heads ,ly:grob-array? "An array of note heads.") |