From 82b1b61dfe18520b6bb197f7772d451dd43986da Mon Sep 17 00:00:00 2001
From: hanwen <hanwen>
Date: Wed, 13 Nov 2002 00:53:03 +0000
Subject: [PATCH] *** empty log message ***

---
 lily/cluster-engraver.cc | 188 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 188 insertions(+)
 create mode 100644 lily/cluster-engraver.cc

diff --git a/lily/cluster-engraver.cc b/lily/cluster-engraver.cc
new file mode 100644
index 0000000000..a9bd545314
--- /dev/null
+++ b/lily/cluster-engraver.cc
@@ -0,0 +1,188 @@
+/*
+  cluster-engraver.cc -- implement Cluster_engraver
+
+  (c) 2002 Juergen Reuter <reuter@ipd.uka.de>
+*/
+
+#include "engraver.hh"
+#include "item.hh"
+#include "spanner.hh"
+#include "note-head.hh"
+#include "warn.hh"
+
+class Cluster_engraver : public Engraver
+{
+
+protected:
+TRANSLATOR_DECLARATIONS(Cluster_engraver);
+  virtual void start_translation_timestep ();
+  virtual bool try_music (Music *);
+  virtual void process_music ();  
+  virtual void acknowledge_grob (Grob_info);
+  virtual void stop_translation_timestep ();
+
+private:
+  Drul_array<Music*> reqs_drul_;
+  Pitch pitch_min, pitch_max;
+  Spanner *cluster;
+  SCM columns_scm;
+};
+
+void reset_min_max (Pitch *pitch_min, Pitch *pitch_max)
+{
+  /*
+   * (pitch_min > pitch_max) means that pitches are not yet
+   * initialized
+   */
+  *pitch_min = Pitch (0, 0, +1);
+  *pitch_max = Pitch (0, 0, -1);
+}
+
+Cluster_engraver::Cluster_engraver ()
+{
+  cluster = 0;
+  columns_scm = SCM_EOL;
+  reqs_drul_[LEFT] = reqs_drul_[RIGHT] = 0;
+}
+
+bool
+Cluster_engraver::try_music (Music *m)
+{
+  if (m->is_mus_type ("abort-event"))
+    {
+      reqs_drul_[START] = 0;
+      reqs_drul_[STOP] = 0;
+      if (cluster)
+	{
+	  cluster->suicide ();
+	  cluster = 0;
+	  columns_scm = SCM_EOL;
+	}
+    }
+  else if (m->is_mus_type ("cluster-event"))
+    {
+      Direction d = to_dir (m->get_mus_property ("span-direction"));
+      reqs_drul_[d] = m;
+      return true;
+    }
+  return false;
+}
+
+void
+Cluster_engraver::process_music ()
+{
+  if (reqs_drul_[STOP])
+    {
+      if (!cluster)
+	{
+	  reqs_drul_[STOP]->origin ()->warning ("can't find start of cluster");
+	}
+      else
+	{
+	  Grob *bound = unsmob_grob (get_property ("currentMusicalColumn"));
+	  cluster->set_bound (RIGHT, bound);
+	  cluster->set_grob_property ("segments", columns_scm);
+	  typeset_grob (cluster);
+	  cluster = 0;
+	  columns_scm = SCM_EOL;
+	}
+      reqs_drul_[STOP] = 0;
+    }
+  if (reqs_drul_[START])
+    {
+      if (cluster)
+	{
+	  reqs_drul_[START]->origin ()->warning ("may not nest clusters");
+	}
+      else
+	{
+	  SCM basicProperties = get_property ("Cluster");
+	  cluster = new Spanner (basicProperties);
+	  columns_scm = SCM_EOL;
+	  Grob *bound = unsmob_grob (get_property ("currentMusicalColumn"));
+	  cluster->set_bound (LEFT, bound);
+	  announce_grob (cluster, bound->self_scm ());
+	}
+      reqs_drul_[START] = 0;
+    }
+}
+
+void
+Cluster_engraver::start_translation_timestep ()
+{
+  reset_min_max (&pitch_min, &pitch_max);
+}
+
+void
+Cluster_engraver::stop_translation_timestep ()
+{
+  if (cluster)
+    {
+      SCM column_scm = get_property ("currentMusicalColumn");
+      if (column_scm == SCM_EOL)
+	{
+	  programming_error("failed retrieving current column");
+	  return;
+	}
+
+      if (Pitch::compare (pitch_min, pitch_max) <= 0)
+	{
+	  int staff_position = pitch_min.steps ();
+	  SCM c0 = get_property ("centralCPosition");
+	  if (gh_number_p (c0))
+	    staff_position += gh_scm2int (c0);
+	  SCM segment = scm_list_n (column_scm,
+				    gh_int2scm (staff_position),
+				    pitch_min.smobbed_copy (),
+				    pitch_max.smobbed_copy (),
+				    SCM_UNDEFINED);
+	  segment = scm_list_n (segment, SCM_UNDEFINED);
+	  columns_scm = (columns_scm != SCM_EOL) ?
+	    gh_append2 (columns_scm, segment) : segment;
+	}
+      else
+	{
+	  /* This timestep is caused by a different voice of the same
+	     staff and hence should be ignored. */
+	}
+    }
+}
+
+void
+Cluster_engraver::acknowledge_grob (Grob_info info)
+{
+  Item *item = dynamic_cast <Item *>(info.grob_);
+  if (item)
+    {
+      if (Note_head::has_interface (info.grob_))
+	{
+	  Music *nr = info.music_cause ();
+	  if (nr && nr->is_mus_type ("note-event"))
+	    {
+	      Pitch pitch = *unsmob_pitch (nr->get_mus_property ("pitch"));
+	      if (Pitch::compare (pitch_min, pitch_max) > 0) // already init'd?
+		{
+		  // not yet init'd; use current pitch to init min/max
+		  pitch_min = pitch;
+		  pitch_max = pitch;
+		}
+	      else if (Pitch::compare (pitch, pitch_max) > 0) // new max?
+		{
+		  pitch_max = pitch;
+		}
+	      else if (Pitch::compare (pitch, pitch_min) < 0) // new min?
+		{
+		  pitch_min = pitch;
+		}
+	    }
+	}
+    }
+}
+
+ENTER_DESCRIPTION(Cluster_engraver,
+/* descr */	"engraves a cluster",
+/* creats*/	"Cluster",
+/* accepts */	"cluster-event",
+/* acks  */	"note-head-interface",
+/* reads */	"",
+/* write */	"");
-- 
2.39.5