2 spacing-engraver.cc -- implement Spacing_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 1999--2001 Han-Wen Nienhuys <hanwen@cs.uu.nl>
10 #include "musical-request.hh"
11 #include "paper-column.hh"
13 #include "spacing-spanner.hh"
14 #include "engraver.hh"
25 Rhythmic_tuple (Grob_info i, Moment m)
30 static int time_compare (Rhythmic_tuple const &, Rhythmic_tuple const &);
34 Acknowledge rhythmic elements, for initializing spacing fields in
37 should be the last one of the toplevel context
39 class Spacing_engraver : public Engraver
41 PQueue<Rhythmic_tuple> playing_durations_;
42 Array<Rhythmic_tuple> now_durations_;
43 Array<Rhythmic_tuple> stopped_durations_;
47 TRANSLATOR_DECLARATIONS(Spacing_engraver);
49 virtual void acknowledge_grob (Grob_info);
50 virtual void start_translation_timestep ();
51 virtual void stop_translation_timestep ();
52 virtual void initialize ();
53 virtual void finalize ();
57 compare (Rhythmic_tuple const &a, Rhythmic_tuple const &b)
59 return Rhythmic_tuple::time_compare (a,b);
63 Rhythmic_tuple::time_compare (Rhythmic_tuple const &h1,
64 Rhythmic_tuple const &h2)
66 return (h1.end_ - h2.end_).main_part_.sign ();
69 Spacing_engraver::Spacing_engraver ()
75 Spacing_engraver::initialize ()
77 spacing_p_ =new Spanner (get_property ("SpacingSpanner"));
78 Spacing_spanner::set_interface (spacing_p_);
79 spacing_p_->set_bound (LEFT, unsmob_grob (get_property ("currentCommandColumn")));
80 announce_grob (spacing_p_, 0);
84 Spacing_engraver::finalize ()
86 Grob * p = unsmob_grob (get_property ("currentCommandColumn"));
87 spacing_p_->set_bound (RIGHT, p);
88 typeset_grob (spacing_p_);
93 Spacing_engraver::acknowledge_grob (Grob_info i)
95 if (to_boolean (i.grob_l_->get_grob_property ("non-rhythmic")))
98 if (Rhythmic_req * r = dynamic_cast<Rhythmic_req*> (i.req_l_))
100 Rhythmic_tuple t (i, now_mom () + r->length_mom ());
101 now_durations_.push (t);
106 Spacing_engraver::stop_translation_timestep ()
108 Moment shortest_playing;
109 shortest_playing.set_infinite (1);
110 for (int i=0; i < playing_durations_.size (); i++)
112 Moment m = (playing_durations_[i].info_.req_l_)->length_mom ();
115 shortest_playing = shortest_playing <? m;
120 inf.set_infinite (1);
122 for (int i=0; i < now_durations_.size (); i++)
124 Moment m = now_durations_[i].info_.req_l_->length_mom ();
126 starter = starter <? m;
128 playing_durations_.insert (now_durations_[i]);
130 now_durations_.clear ();
132 shortest_playing = shortest_playing <? starter;
135 = dynamic_cast<Paper_column*> (unsmob_grob (get_property ("currentMusicalColumn")));
137 SCM sh = shortest_playing.smobbed_copy ();
138 SCM st = starter.smobbed_copy ();
140 sc->set_grob_property ("shortest-playing-duration", sh);
141 sc->set_grob_property ("shortest-starter-duration", st);
145 Spacing_engraver::start_translation_timestep ()
147 Moment now = now_mom ();
148 stopped_durations_.clear ();
149 while (playing_durations_.size () && playing_durations_.front ().end_ < now)
150 playing_durations_.delmin ();
151 while (playing_durations_.size () && playing_durations_.front ().end_ == now)
152 stopped_durations_.push (playing_durations_.get ());
158 ENTER_DESCRIPTION(Spacing_engraver,
159 /* descr */ "make a SpacingSpanner and do bookkeeping of shortest starting and playing notes ",
160 /* creats*/ "SpacingSpanner",
161 /* acks */ "grob-interface",