]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/porrectus-engraver.cc
* ly/engraver-init.ly: use Hara kiri by default for
[lilypond.git] / lily / porrectus-engraver.cc
index 84d81f44605a449bd63494f301d259b63483b4b3..fab7e7d86ef4c6220fe7dbf484a2c1279a407d75 100644 (file)
@@ -1,7 +1,7 @@
 /*
   porrectus-engraver.cc -- implement Porrectus_engraver
 
-  Copyright (C) 2001 Juergen Reuter
+  Copyright (c) 2001--2003  Juergen Reuter
 
   written for the GNU LilyPond music typesetter
 */
  * moment of the second note.  Actually, it should take the moment of
  * the first note.
  *
- * TODO: Introduce "\~" as alternative syntax for "\porrectus"?
+ * FIXME: Turn off typesetting of stems, flags, dots, etc.
  *
  * TODO: Hufnagel support.
  *
- * TODO: Fine-tuning of porrectus shape.  In particular, the mensural
- * non-solid shape could either be slightly bigger in height, or the
- * extrem points could be slightly vertically shifted apart.
+ * TODO: The following issues are currently not handled by this
+ * engraver: (1) accidentals placement, (2) spacing.  For example,
+ * currently only the accidental for the second note (cp. the above
+ * FIXME) is printed.  These issues should be resolved by some sort of
+ * ligature context that encloses use of this engraver, using syntax
+ * like: \ligature { e \~ c }.
  *
- * TODO: For white mensural (i.e. #'style=#'mensural, #'solid=##f)
- * porrectus grobs, it is possible to automatically determine all
- * porrectus specific properties (add-stem, stem-direction) solely
- * from the duration of the contributing notes and time-signature.
- * Introduce a boolean grob property called auto-config, so that, if
- * turned on, lily automatically sets the remaining properties
- * properly.
+ * TODO: Do not allow a series of adjacent porrectus events, as in:
+ * e \~ d \~ c.
  *
- * TODO: The following issues are not (and should not be) handled by
- * this engraver: (1) accidentals placement, (2) avoiding line
- * breaking inbetween porrectus, (3) spacing.  For example, currently
- * only the accidental for the second note (cp. the above FIXME) is
- * printed.  These issues should be resolved by some sort of ligature
- * context that encloses use of this engraver, using syntax like:
- * \ligature { e \porrectus c }.
- *
- * TODO: Do not allow a series of adjacent porrectus requests, as in:
- * e \porrectus d \porrectus c.
+ * TODO: Junk duplicate (or rather triple) implementation of
+ * create_ledger_line in porrectus.cc, custos.cc and note-head.cc.
  */
 
 #include "staff-symbol-referencer.hh"
 #include "porrectus.hh"
-#include "musical-request.hh"
-#include "command-request.hh"
+#include "event.hh"
+
 #include "rhythmic-head.hh"
 #include "item.hh"
 #include "engraver.hh"
+#include "score-engraver.hh"
 #include "pqueue.hh"
-
-// TODO: PHead_melodic_tuple is duplicated code from tie-engraver.cc.
-// Maybe put this into public class?
-struct PHead_melodic_tuple {
-  Melodic_req *req_l_;
-  Grob *head_l_;
-  Moment end_;
-  PHead_melodic_tuple ();
-  PHead_melodic_tuple (Grob*, Melodic_req*, Moment);
-  static int pitch_compare (PHead_melodic_tuple const &,
-                           PHead_melodic_tuple const &);
-  static int time_compare (PHead_melodic_tuple const &,
-                          PHead_melodic_tuple const &);  
-};
-
-inline int compare (PHead_melodic_tuple const &a, PHead_melodic_tuple const &b)
-{
-  return PHead_melodic_tuple::time_compare (a,b);
-}
+#include "warn.hh"
+#include "grob-pitch-tuple.hh"
 
 class Porrectus_engraver : public Engraver {
 public:
-  Porrectus_engraver ();
-  VIRTUAL_COPY_CONS (Translator);
+  TRANSLATOR_DECLARATIONS(Porrectus_engraver);
   
 protected:
-  virtual bool try_music (Music *req_l);
-  virtual void create_grobs ();
+  virtual bool try_music (Music *req);
+  virtual void process_music ();
+  virtual void process_acknowledged_grobs ();
   virtual void stop_translation_timestep ();
   virtual void start_translation_timestep ();
   virtual void acknowledge_grob (Grob_info);
 
 private:
-  PQueue<PHead_melodic_tuple> past_notes_pq_;
-  Porrectus_req *porrectus_req_l_;
-  Array<PHead_melodic_tuple> left_heads_;
-  Array<PHead_melodic_tuple> right_heads_;
-  Link_array<Grob> porrectus_p_arr_;
+  PQueue<Grob_pitch_tuple> past_notes_pq_;
+  Music *porrectus_req_;
+  Array<Grob_pitch_tuple> left_heads_;
+  Array<Grob_pitch_tuple> right_heads_;
+  Link_array<Grob> porrectuses_;
 };
 
 Porrectus_engraver::Porrectus_engraver ()
 {
-  porrectus_req_l_ = 0;
+  porrectus_req_ = 0;
 }
 
 bool
 Porrectus_engraver::try_music (Music *m)
 {
-  if (Porrectus_req *req_l_ = dynamic_cast <Porrectus_req *> (m))
+  if (m->is_mus_type ("porrectus-event"))
     {
-      porrectus_req_l_ = req_l_;
+      porrectus_req_ = m;
       return true;
     }
   else
@@ -105,133 +79,95 @@ Porrectus_engraver::try_music (Music *m)
 }
 
 void
-Porrectus_engraver::acknowledge_grob (Grob_info info_l_)
+Porrectus_engraver::process_music ()
 {
-  if (Rhythmic_head::has_interface (info_l_.elem_l_))
+  if (porrectus_req_)
     {
-      Note_req *note_req_l_ = dynamic_cast <Note_req *> (info_l_.req_l_);
-      if (!note_req_l_)
-       return;
-      left_heads_.push (PHead_melodic_tuple (info_l_.elem_l_, note_req_l_,
-                                            now_mom () +
-                                            note_req_l_->length_mom ()));
+      top_engraver ()->forbid_breaks ();
     }
 }
 
 void
-Porrectus_engraver::create_grobs ()
+Porrectus_engraver::acknowledge_grob (Grob_info info_)
 {
-  if (porrectus_req_l_)
+  if (Rhythmic_head::has_interface (info_.grob_))
     {
-      left_heads_.sort (PHead_melodic_tuple::pitch_compare);
-      right_heads_.sort (PHead_melodic_tuple::pitch_compare);
+      Music * m = info_.music_cause ();
+      if (m->is_mus_type ("note-event"))
+       right_heads_.push (Grob_pitch_tuple (info_.grob_, m,
+                                            now_mom () +
+                                            m->get_length ()));
+    }
+}
 
-      SCM head_list = SCM_EOL;
-      
+void
+Porrectus_engraver::process_acknowledged_grobs ()
+{
+  if (porrectus_req_)
+    {
+      left_heads_.sort (Grob_pitch_tuple::pitch_compare);
+      right_heads_.sort (Grob_pitch_tuple::pitch_compare);
       int i = left_heads_.size () - 1;
       int j = right_heads_.size () - 1;
 
       while ((i >= 0) && (j >= 0))
        {
-         head_list =
-           gh_cons (gh_cons (right_heads_[j].head_l_->self_scm (),
-                             left_heads_[i].head_l_->self_scm ()),
-                    head_list);
+         Item *left_head = dynamic_cast<Item*> (left_heads_[i].head_);
+         Item *right_head = dynamic_cast<Item*> (right_heads_[j].head_);
+         left_head->set_grob_property("transparent", gh_bool2scm(true));
+         right_head->set_grob_property("transparent", gh_bool2scm(true));
 
-         past_notes_pq_. insert (left_heads_[i]);
+         Grob *porrectus_ = new Item (get_property ("Porrectus"));
+         Porrectus::set_left_head(porrectus_, left_head);
+         Porrectus::set_right_head(porrectus_, right_head);
+         porrectuses_.push (porrectus_);
+         announce_grob(porrectus_, porrectus_req_->self_scm());
+
+         past_notes_pq_. insert (right_heads_[i]);
          left_heads_.del (i);
          right_heads_.del (j);
          i--;
          j--;
        }
-
-      for (SCM s = head_list; gh_pair_p (s); s = gh_cdr (s))
-       {
-         SCM caar = gh_caar (s);
-         SCM cdar = gh_cdar (s);
-
-         Item *left_head = dynamic_cast<Item*> (unsmob_grob (caar));
-         Item *right_head = dynamic_cast<Item*> (unsmob_grob (cdar));
-         left_head->set_grob_property("transparent", gh_bool2scm(true));
-         right_head->set_grob_property("transparent", gh_bool2scm(true));
-
-         Grob *porrectus_p_ = new Item (get_property ("Porrectus"));
-         Porrectus::set_left_head(porrectus_p_, caar);
-         Porrectus::set_right_head(porrectus_p_, cdar);
-         porrectus_p_arr_.push (porrectus_p_);
-         announce_grob (porrectus_p_, 0);
-       }
     }
 }
 
 void
 Porrectus_engraver::stop_translation_timestep ()
 {
-  for (int i = 0; i < left_heads_.size (); i++)
+  for (int i = 0; i < right_heads_.size (); i++)
     {
-      past_notes_pq_.insert (left_heads_[i]);
+      past_notes_pq_.insert (right_heads_[i]);
     }
-  left_heads_.clear ();
+  right_heads_.clear ();
 
-  for (int i = 0; i < porrectus_p_arr_.size (); i++)
+  for (int i = 0; i < porrectuses_.size (); i++)
     {
-      typeset_grob (porrectus_p_arr_[i]);
+      typeset_grob (porrectuses_[i]);
     }
-  porrectus_p_arr_.clear ();
+  porrectuses_.clear ();
 }
 
 void
 Porrectus_engraver::start_translation_timestep ()
 {
-  porrectus_req_l_ = 0;
+  porrectus_req_ = 0;
   Moment now = now_mom ();
   while (past_notes_pq_.size () && past_notes_pq_.front ().end_ < now)
     past_notes_pq_.delmin ();
 
-  right_heads_.clear ();
+  left_heads_.clear ();
   while (past_notes_pq_.size () &&
         (past_notes_pq_.front ().end_ == now))
-    right_heads_.push (past_notes_pq_.get ());
+    left_heads_.push (past_notes_pq_.get ());
 }
 
-ADD_THIS_TRANSLATOR (Porrectus_engraver);
 
-// TODO: PHead_melodic_tuple is duplicated code from tie-engraver.cc.
-// Maybe put this into public class?
 
-PHead_melodic_tuple::PHead_melodic_tuple ()
-{
-  head_l_ = 0;
-  req_l_ = 0;
-  end_ = 0;
-}
-
-PHead_melodic_tuple::PHead_melodic_tuple (Grob *h, Melodic_req*m, Moment mom)
-{
-  head_l_ = h;
-  req_l_ = m;
-  end_ = mom;
-}
-
-/*
-  signed compare, should use pitch<? 
- */
-int
-PHead_melodic_tuple::pitch_compare (PHead_melodic_tuple const&h1,
-                                   PHead_melodic_tuple const &h2)
-{
-  SCM p1 = h1.req_l_->get_mus_property ("pitch");
-  SCM p2 = h2.req_l_->get_mus_property ("pitch");
-  
-  int result = Pitch::compare (*unsmob_pitch (p1),
-                              *unsmob_pitch (p2));
-  return result;
-}
-
-int
-PHead_melodic_tuple::time_compare (PHead_melodic_tuple const&h1,
-                                  PHead_melodic_tuple const &h2)
-{
-  int result = Moment::compare(h1.end_,  h2.end_);
-  return result;
-}
+ENTER_DESCRIPTION(Porrectus_engraver,
+/* descr */       "Join adjacent notes to a porrectus ligature.",
+/* creats*/       "Porrectus",
+/* accepts */     "porrectus-event",
+/* acks  */      "rhythmic-head-interface",
+/* reads */       "",
+/* write */       "");