2 new-chord-tremolo-engraver.cc -- implement Chord_tremolo_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 2000--2005 Han-Wen Nienhuys <hanwen@cs.uu.nl>
11 #include "repeated-music.hh"
13 #include "rhythmic-head.hh"
14 #include "engraver-group-engraver.hh"
17 #include "note-head.hh"
20 #include "chord-tremolo-iterator.hh"
21 #include "stem-tremolo.hh"
22 #include "math.h" // ceil
26 This acknowledges repeated music with "tremolo" style. It typesets
31 - perhaps use engraver this to steer other engravers? That would
32 create dependencies between engravers, which is bad.
34 - create dots if appropriate.
36 - create TremoloBeam iso Beam?
39 class Chord_tremolo_engraver : public Engraver
42 TRANSLATOR_DECLARATIONS (Chord_tremolo_engraver);
46 /// moment (global time) where beam started.
50 int total_duration_flags_;
52 /// location within measure where beam started.
53 Moment beam_start_location_;
55 bool body_is_sequential_;
57 Spanner * finished_beam_;
60 virtual void finalize ();
61 virtual bool try_music (Music*);
62 virtual void acknowledge_grob (Grob_info);
63 virtual void stop_translation_timestep ();
64 virtual void start_translation_timestep ();
65 virtual void process_music ();
68 Chord_tremolo_engraver::Chord_tremolo_engraver ()
70 beam_ = finished_beam_ = 0;
74 body_is_sequential_ = false;
78 Chord_tremolo_engraver::try_music (Music * m)
80 if (m->is_mus_type ("repeated-music")
81 && m->get_property ("iterator-ctor") == Chord_tremolo_iterator::constructor_proc
84 Moment l = m->get_length ();
86 start_mom_ = now_mom ();
87 stop_mom_ = start_mom_ + l;
90 Music *body = Repeated_music::body (m);
91 body_is_sequential_ = body->is_mus_type ("sequential-music");
93 int elt_count = body_is_sequential_ ? scm_ilength (body->get_property ("elements")) : 1;
95 if (body_is_sequential_ && elt_count != 2)
97 m->origin ()->warning (_f ("Chord tremolo with %d elements. Must have two elements.", elt_count));
103 Rational total_dur = l.main_part_;
104 Rational note_dur = total_dur / Rational (elt_count * Repeated_music::repeat_count (repeat_));
106 total_duration_flags_ = 0 >? (intlog2 (total_dur.den ()) - 2);
108 flags_ = intlog2 (note_dur.den ()) -2 ;
117 Chord_tremolo_engraver::process_music ()
119 if (repeat_ && body_is_sequential_ && !beam_)
121 beam_ = make_spanner ("Beam", repeat_->self_scm ());
122 beam_->set_property ("chord-tremolo", SCM_BOOL_T);
124 beam_start_location_ = robust_scm2moment (get_property ("measurePosition"), Moment (0));
129 Chord_tremolo_engraver::finalize ()
134 repeat_->origin ()->warning (_ ("unterminated chord tremolo"));
140 Chord_tremolo_engraver::typeset_beam ()
146 Chord_tremolo_engraver::acknowledge_grob (Grob_info info)
148 if (beam_ && Stem::has_interface (info.grob_))
150 Grob * s = info.grob_;
152 if (start_mom_ == now_mom ())
153 Stem::set_beaming (s, flags_, RIGHT);
155 Stem::set_beaming (s, flags_, LEFT);
157 if (Stem::duration_log (s) != 1)
159 beam_->set_property ("gap-count", scm_int2num (flags_ - total_duration_flags_));
162 if (info.music_cause ()->is_mus_type ("rhythmic-event"))
164 Beam::add_stem (beam_, s);
168 String s = _ ("stem must have Rhythmic structure");
169 if (info.music_cause ())
170 info.music_cause ()->origin ()->warning (s);
176 flags_ && !body_is_sequential_ && Stem::has_interface (info.grob_))
178 stem_tremolo_ = make_item ("StemTremolo", repeat_->self_scm ());
179 stem_tremolo_->set_property ("flag-count",
180 scm_int2num (flags_));
181 stem_tremolo_->set_property ("stem",
182 info.grob_->self_scm ());
183 stem_tremolo_->set_parent (info.grob_, X_AXIS);
189 Chord_tremolo_engraver::start_translation_timestep ()
191 if (beam_ && stop_mom_ == now_mom ())
193 finished_beam_ = beam_;
201 Chord_tremolo_engraver::stop_translation_timestep ()
207 programming_error ("Huh, beam and stem tremolo?");
216 ADD_TRANSLATOR (Chord_tremolo_engraver,
217 /* descr */ "Generates beams for tremolo repeats.",
219 /* accepts */ "repeated-music",
220 /* acks */ "stem-interface note-head-interface",