]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/cluster-engraver.cc
(warning): better robustness fix.
[lilypond.git] / lily / cluster-engraver.cc
index a9bd545314797a19250c787e68f401c8d4b67a70..4308326c535f1d8f1e3130ee6796b31d80120e8d 100644 (file)
@@ -8,6 +8,7 @@
 #include "item.hh"
 #include "spanner.hh"
 #include "note-head.hh"
+#include "protected-scm.hh"
 #include "warn.hh"
 
 class Cluster_engraver : public Engraver
@@ -23,9 +24,9 @@ TRANSLATOR_DECLARATIONS(Cluster_engraver);
 
 private:
   Drul_array<Music*> reqs_drul_;
-  Pitch pitch_min, pitch_max;
-  Spanner *cluster;
-  SCM columns_scm;
+  Pitch pitch_min_, pitch_max_;
+  Spanner *cluster_;
+  SCM columns_scm_;
 };
 
 void reset_min_max (Pitch *pitch_min, Pitch *pitch_max)
@@ -40,8 +41,8 @@ void reset_min_max (Pitch *pitch_min, Pitch *pitch_max)
 
 Cluster_engraver::Cluster_engraver ()
 {
-  cluster = 0;
-  columns_scm = SCM_EOL;
+  cluster_ = 0;
+  columns_scm_ = SCM_EOL;
   reqs_drul_[LEFT] = reqs_drul_[RIGHT] = 0;
 }
 
@@ -52,11 +53,11 @@ Cluster_engraver::try_music (Music *m)
     {
       reqs_drul_[START] = 0;
       reqs_drul_[STOP] = 0;
-      if (cluster)
+      if (cluster_)
        {
-         cluster->suicide ();
-         cluster = 0;
-         columns_scm = SCM_EOL;
+         cluster_->suicide ();
+         cluster_ = 0;
+         columns_scm_ = SCM_EOL;
        }
     }
   else if (m->is_mus_type ("cluster-event"))
@@ -73,35 +74,30 @@ Cluster_engraver::process_music ()
 {
   if (reqs_drul_[STOP])
     {
-      if (!cluster)
+      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;
+         cluster_->set_bound (RIGHT, bound);
        }
-      reqs_drul_[STOP] = 0;
     }
   if (reqs_drul_[START])
     {
-      if (cluster)
+      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;
+         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 ());
+         cluster_->set_bound (LEFT, bound);
+         announce_grob (cluster_, bound->self_scm ());
        }
       reqs_drul_[START] = 0;
     }
@@ -110,40 +106,55 @@ Cluster_engraver::process_music ()
 void
 Cluster_engraver::start_translation_timestep ()
 {
-  reset_min_max (&pitch_min, &pitch_max);
+  reset_min_max (&pitch_min_, &pitch_max_);
 }
 
 void
 Cluster_engraver::stop_translation_timestep ()
 {
-  if (cluster)
+  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)
+      else
        {
-         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;
+         if (Pitch::compare (pitch_min_, pitch_max_) <= 0)
+           {
+             Real y_bottom = 0.5 * pitch_min_.steps ();
+             SCM c0 = get_property ("centralCPosition");
+             if (gh_number_p (c0))
+               y_bottom += 0.5 * gh_scm2int (c0);
+             else
+               programming_error ("Cluster_engraver: failed evaluating c0");
+             Real y_top = y_bottom +
+               0.5 * (pitch_max_.steps () - pitch_min_.steps ());
+             column_scm = Protected_scm (column_scm);
+             SCM segment = scm_list_n (column_scm,
+                                       gh_double2scm (y_bottom),
+                                       gh_double2scm (y_top),
+                                       SCM_UNDEFINED);
+             segment = scm_list_n (segment, SCM_UNDEFINED);
+             columns_scm_ = (columns_scm_ != SCM_EOL) ?
+               gh_append2 (columns_scm_, segment) : segment;
+             cluster_->set_grob_property ("segments", columns_scm_); // Urrgh!
+           }
+         else
+           {
+             /* This timestep is caused by a different voice of the
+                same staff and hence should be ignored. */
+           }
        }
-      else
+
+      if (reqs_drul_[STOP])
        {
-         /* This timestep is caused by a different voice of the same
-            staff and hence should be ignored. */
+         reqs_drul_[STOP] = 0;
+         cluster_->set_grob_property ("segments", columns_scm_);
+         typeset_grob (cluster_);
+         cluster_ = 0;
+         columns_scm_ = SCM_EOL;
        }
     }
 }
@@ -160,19 +171,19 @@ Cluster_engraver::acknowledge_grob (Grob_info info)
          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?
+             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;
+                 pitch_min_ = pitch;
+                 pitch_max_ = pitch;
                }
-             else if (Pitch::compare (pitch, pitch_max) > 0) // new max?
+             else if (Pitch::compare (pitch, pitch_max_) > 0) // new max?
                {
-                 pitch_max = pitch;
+                 pitch_max_ = pitch;
                }
-             else if (Pitch::compare (pitch, pitch_min) < 0) // new min?
+             else if (Pitch::compare (pitch, pitch_min_) < 0) // new min?
                {
-                 pitch_min = pitch;
+                 pitch_min_ = pitch;
                }
            }
        }