2002->2003
[lilypond.git] / lily / porrectus-engraver.cc
blobfab7e7d86ef4c6220fe7dbf484a2c1279a407d75
1 /*
2 porrectus-engraver.cc -- implement Porrectus_engraver
4 Copyright (c) 2001--2003 Juergen Reuter
6 written for the GNU LilyPond music typesetter
7 */
9 /*
10 * FIXME: Currently, when creating a porrectus item, it takes the
11 * moment of the second note. Actually, it should take the moment of
12 * the first note.
14 * FIXME: Turn off typesetting of stems, flags, dots, etc.
16 * TODO: Hufnagel support.
18 * TODO: The following issues are currently not handled by this
19 * engraver: (1) accidentals placement, (2) spacing. For example,
20 * currently only the accidental for the second note (cp. the above
21 * FIXME) is printed. These issues should be resolved by some sort of
22 * ligature context that encloses use of this engraver, using syntax
23 * like: \ligature { e \~ c }.
25 * TODO: Do not allow a series of adjacent porrectus events, as in:
26 * e \~ d \~ c.
28 * TODO: Junk duplicate (or rather triple) implementation of
29 * create_ledger_line in porrectus.cc, custos.cc and note-head.cc.
32 #include "staff-symbol-referencer.hh"
33 #include "porrectus.hh"
34 #include "event.hh"
36 #include "rhythmic-head.hh"
37 #include "item.hh"
38 #include "engraver.hh"
39 #include "score-engraver.hh"
40 #include "pqueue.hh"
41 #include "warn.hh"
42 #include "grob-pitch-tuple.hh"
44 class Porrectus_engraver : public Engraver {
45 public:
46 TRANSLATOR_DECLARATIONS(Porrectus_engraver);
48 protected:
49 virtual bool try_music (Music *req);
50 virtual void process_music ();
51 virtual void process_acknowledged_grobs ();
52 virtual void stop_translation_timestep ();
53 virtual void start_translation_timestep ();
54 virtual void acknowledge_grob (Grob_info);
56 private:
57 PQueue<Grob_pitch_tuple> past_notes_pq_;
58 Music *porrectus_req_;
59 Array<Grob_pitch_tuple> left_heads_;
60 Array<Grob_pitch_tuple> right_heads_;
61 Link_array<Grob> porrectuses_;
64 Porrectus_engraver::Porrectus_engraver ()
66 porrectus_req_ = 0;
69 bool
70 Porrectus_engraver::try_music (Music *m)
72 if (m->is_mus_type ("porrectus-event"))
74 porrectus_req_ = m;
75 return true;
77 else
78 return false;
81 void
82 Porrectus_engraver::process_music ()
84 if (porrectus_req_)
86 top_engraver ()->forbid_breaks ();
90 void
91 Porrectus_engraver::acknowledge_grob (Grob_info info_)
93 if (Rhythmic_head::has_interface (info_.grob_))
95 Music * m = info_.music_cause ();
96 if (m->is_mus_type ("note-event"))
97 right_heads_.push (Grob_pitch_tuple (info_.grob_, m,
98 now_mom () +
99 m->get_length ()));
103 void
104 Porrectus_engraver::process_acknowledged_grobs ()
106 if (porrectus_req_)
108 left_heads_.sort (Grob_pitch_tuple::pitch_compare);
109 right_heads_.sort (Grob_pitch_tuple::pitch_compare);
110 int i = left_heads_.size () - 1;
111 int j = right_heads_.size () - 1;
113 while ((i >= 0) && (j >= 0))
115 Item *left_head = dynamic_cast<Item*> (left_heads_[i].head_);
116 Item *right_head = dynamic_cast<Item*> (right_heads_[j].head_);
117 left_head->set_grob_property("transparent", gh_bool2scm(true));
118 right_head->set_grob_property("transparent", gh_bool2scm(true));
120 Grob *porrectus_ = new Item (get_property ("Porrectus"));
121 Porrectus::set_left_head(porrectus_, left_head);
122 Porrectus::set_right_head(porrectus_, right_head);
123 porrectuses_.push (porrectus_);
124 announce_grob(porrectus_, porrectus_req_->self_scm());
126 past_notes_pq_. insert (right_heads_[i]);
127 left_heads_.del (i);
128 right_heads_.del (j);
129 i--;
130 j--;
135 void
136 Porrectus_engraver::stop_translation_timestep ()
138 for (int i = 0; i < right_heads_.size (); i++)
140 past_notes_pq_.insert (right_heads_[i]);
142 right_heads_.clear ();
144 for (int i = 0; i < porrectuses_.size (); i++)
146 typeset_grob (porrectuses_[i]);
148 porrectuses_.clear ();
151 void
152 Porrectus_engraver::start_translation_timestep ()
154 porrectus_req_ = 0;
155 Moment now = now_mom ();
156 while (past_notes_pq_.size () && past_notes_pq_.front ().end_ < now)
157 past_notes_pq_.delmin ();
159 left_heads_.clear ();
160 while (past_notes_pq_.size () &&
161 (past_notes_pq_.front ().end_ == now))
162 left_heads_.push (past_notes_pq_.get ());
167 ENTER_DESCRIPTION(Porrectus_engraver,
168 /* descr */ "Join adjacent notes to a porrectus ligature.",
169 /* creats*/ "Porrectus",
170 /* accepts */ "porrectus-event",
171 /* acks */ "rhythmic-head-interface",
172 /* reads */ "",
173 /* write */ "");