]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/note-spacing-engraver.cc
Run `make grand-replace'.
[lilypond.git] / lily / note-spacing-engraver.cc
index 47b11ae5ac9f57271b943c4670be328eafccf909..8a5f5c7944228753efbc518241bf09773827fac6 100644 (file)
-#if 0
-/*   
-  note-spacing-engraver.cc --  implement  Note_spacing_engraver.
-
+/* 
+  note-spacing-engraver.cc -- implement Note_spacing_engraver
+  
   source file of the GNU LilyPond music typesetter
-
-  (c) 2001 Han-Wen Nienhuys <hanwen@cs.uu.nl>
-
+  
+  (c) 2006--2008 Han-Wen Nienhuys <hanwen@lilypond.org>
+  
 */
 
-#include "grob.hh"
-#include "moment.hh"
 #include "engraver.hh"
-#include "note-spacing.hh"
-#include "note-column.hh"
 
-/*
-  Originally, we tried to have this functionality at Staff_level
-  
-  - by simply using the sequence of Separation-item as
-  spacing-sequences. Unfortunately, this fucks up if there are
-  different kinds of tuplets combined (8th and 8ths triplets combined
-  made the program believe there were 1/12 th notes.).
+#include "grob-array.hh"
+#include "context.hh"
+#include "item.hh"
+#include "pointer-group-interface.hh"
 
+#include <map>
 
-  - We also created them from Rhythmic_column_engraver, but this has
-  the problem that voices can appear and disappear at will, leaving
-  lots of loose ends (the StaffSpacing don't know where to connect the
-  last note of the voice on the right with)
-  
- */
+#include "translator.icc"
 
-struct Grob_moment_tuple
+class Note_spacing_engraver : public Engraver
 {
-  Link_array<Grob> current_heads_;
-  Link_array<Grob> todo_heads_;
+  typedef map <Context*, Grob*> Last_spacing_map;
+  Last_spacing_map last_spacings_;
+  Grob *last_spacing_;
   
-  Moment length_;
-  
-  static int time_compare (Grob_moment_tuple const &a, Grob_moment_tuple const &b)
-  {
-    return Moment::compare (a.length_, b.length_);
-  }
+  Grob *spacing_;
+
+  void add_spacing_item (Grob *);
+  TRANSLATOR_DECLARATIONS (Note_spacing_engraver);
+protected:
+
+  DECLARE_ACKNOWLEDGER (rhythmic_grob);
+  DECLARE_ACKNOWLEDGER (note_column);
+  void stop_translation_timestep ();
+  virtual void finalize ();
+  virtual void derived_mark () const;
 };
 
-class Note_spacing_engraver : public Engraver
+void
+Note_spacing_engraver::derived_mark () const
 {
-public:
-  TRANSLATOR_DECLARATIONS(Note_spacing_engraver);
+  for (Last_spacing_map::const_iterator i = last_spacings_.begin ();
+       i != last_spacings_.end (); i++)
+    scm_gc_mark (i->first->self_scm ());
+}
 
+Note_spacing_engraver::Note_spacing_engraver ()
+{
+  spacing_ = 0;
+  last_spacing_ = 0;
+}
 
-protected:
-  Array<Grob_moment_tuple> lengths_found_;
+void
+Note_spacing_engraver::add_spacing_item (Grob *g)
+{
+  if (!spacing_)
+    {
+      spacing_ = make_item ("NoteSpacing", g->self_scm ());
+    }
+  
+  if (spacing_)
+    {
+      Pointer_group_interface::add_grob (spacing_,
+                                        ly_symbol2scm ("left-items"),
+                                        g);
+
+      if (last_spacing_)
+       Pointer_group_interface::add_grob (last_spacing_,
+                                          ly_symbol2scm ("right-items"),
+                                          g);
+    }
+}
 
-  virtual void acknowledge_grob (Grob_info);
-};
 
-Note_spacing_engraver::Note_spacing_engraver()
+void
+Note_spacing_engraver::acknowledge_note_column (Grob_info gi)
 {
+  add_spacing_item (gi.grob ());
 }
 
+void
+Note_spacing_engraver::acknowledge_rhythmic_grob (Grob_info gi)
+{
+  add_spacing_item (gi.grob ());
+}
 
 void
-Note_spacing_engraver::acknowledge_grob (Grob_info gi)
+Note_spacing_engraver::finalize ()
 {
-  if (Note_head::has_interface (gi.grob_l_))
+  Context *parent = context ()->get_parent_context ();
+  Grob *last_spacing = last_spacings_[parent];
+
+  if (last_spacing
+      && !unsmob_grob_array (last_spacing->get_object ("right-items")))
     {
-      Music *m = gi.music_cause();
-      Moment now = now_mom ();
-      Moment len = m->length_mom(); 
-      if (now.grace_part_ && len.main_part_)
-       {
-         len.grace_part_ += len.main_part_;
-         len.main_part_ = 0;
-       }
+      Grob *col  = unsmob_grob (get_property ("currentCommandColumn"));
       
-      for (int  i=0; i <  
+      Pointer_group_interface::add_grob (last_spacing,
+                                        ly_symbol2scm ("right-items"),
+                                        col);
     }
-  Note_column::has_interface (gi.grob_l_))
-    {
-      Grob *head  =Note_column::first_head (gi.grob_l_);
+}
+
+void
+Note_spacing_engraver::stop_translation_timestep ()
+{
+  Context *parent = context ()->get_parent_context ();
+  Grob *last_spacing = last_spacings_[parent];
 
-      head->
+  if (last_spacing
+      && to_boolean (get_property ("hasStaffSpacing")))
+    {
+      Grob *col = unsmob_grob (get_property ("currentCommandColumn"));
+      Pointer_group_interface::add_grob (last_spacing,
+                                        ly_symbol2scm ("right-items"),
+                                        col);
     }
+  
+  if (spacing_)
+    {
+      last_spacings_[parent] = spacing_;
+      last_spacing_ = spacing_;
+      spacing_ = 0;
+    }
+
 }
 
+ADD_ACKNOWLEDGER (Note_spacing_engraver, note_column);
+ADD_ACKNOWLEDGER (Note_spacing_engraver, rhythmic_grob);
 
+ADD_TRANSLATOR (Note_spacing_engraver,
+               /* doc */
+               "Generate @code{NoteSpacing}, an object linking horizontal"
+               " lines for use in spacing.",
 
-ENTER_DESCRIPTION(Note_spacing_engraver,
-/* descr */       "This engraver creates spacing objects. It should be placed at staff
-level, but will also function at voice level.
+               /* create */
+               "NoteSpacing ",
 
-",
-/* creats*/       "NoteSpacing",
-/* acks  */       "rhythmic-column-interface",
-/* reads */       "",
-/* write */       "");
+               /* read */
+               "",
 
-#endif
+               /* write */
+               ""
+               );