]> git.donarmstrong.com Git - lilypond.git/commitdiff
Allows for individual glissandi between members of NoteColumns.
authorMike Solomon <mike@apollinemike.com>
Thu, 28 Apr 2011 13:10:27 +0000 (09:10 -0400)
committerMike Solomon <mike@apollinemike.com>
Thu, 28 Apr 2011 13:10:27 +0000 (09:10 -0400)
The property glissandoMap is used to tell the glissando-engraver
what note-column members to connect via glissandi.

input/regression/glissando-chord.ly [new file with mode: 0644]
lily/glissando-engraver.cc
scm/define-context-properties.scm
scm/define-grob-interfaces.scm
scm/define-grob-properties.scm

diff --git a/input/regression/glissando-chord.ly b/input/regression/glissando-chord.ly
new file mode 100644 (file)
index 0000000..e140c38
--- /dev/null
@@ -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>
+}
index 99eb6bc515b2aa5675483de2d498c5f0792a556e..08f420c128a10483454418e9389dfa201148a4ee 100644 (file)
@@ -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 */
                ""
index a813f1421f6b90ae8d8d9e7fba41000e8ebcb84a..e9484ba19485df2358101d3ec824d3f5eff530c0 100644 (file)
@@ -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.")
 
index edc02a7fb3ea911d9f63e77ad3b80ca3b0c6a542..a7090de0327ff19fbd57c011ff33f5d4ac695f0d 100644 (file)
@@ -100,7 +100,7 @@ note)."
 (ly:add-interface
   'glissando-interface
   "A glissando."
-  '())
+  '(glissando-index))
 
 (ly:add-interface
  'grace-spacing-interface
index 3381cb9e27ed2858ea1decc3e88b31e4c1d5b97f..7fd0b138190bf35f20d9fcec62934c92af86839b 100644 (file)
@@ -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.")