2 spacing-engraver.cc -- implement Spacing_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 1999--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
9 #include "paper-column.hh"
10 #include "engraver.hh"
12 #include "note-spacing.hh"
13 #include "staff-spacing.hh"
14 #include "pointer-group-interface.hh"
17 #include "translator.icc"
27 Rhythmic_tuple (Grob_info i, Moment m)
32 static int time_compare (Rhythmic_tuple const &, Rhythmic_tuple const &);
36 compare (Rhythmic_tuple const &a, Rhythmic_tuple const &b)
38 return Rhythmic_tuple::time_compare (a, b);
42 Rhythmic_tuple::time_compare (Rhythmic_tuple const &h1,
43 Rhythmic_tuple const &h2)
45 return (h1.end_ - h2.end_).main_part_.sign ();
48 /****************************************************************/
51 Acknowledge rhythmic elements, for initializing spacing fields in
54 class Spacing_engraver : public Engraver
56 PQueue<Rhythmic_tuple> playing_durations_;
57 vector<Rhythmic_tuple> now_durations_;
58 vector<Rhythmic_tuple> stopped_durations_;
61 Music *start_section_;
63 TRANSLATOR_DECLARATIONS (Spacing_engraver);
66 DECLARE_ACKNOWLEDGER (staff_spacing);
67 DECLARE_ACKNOWLEDGER (note_spacing);
68 DECLARE_ACKNOWLEDGER (rhythmic_head);
70 void start_translation_timestep ();
71 void stop_translation_timestep ();
72 void process_music ();
74 virtual void finalize ();
75 virtual bool try_music (Music *m);
77 void start_spanner ();
81 Spacing_engraver::Spacing_engraver ()
88 Spacing_engraver::try_music (Music *m)
95 Spacing_engraver::process_music ()
97 if (start_section_ && spacing_)
105 Spacing_engraver::start_spanner ()
109 spacing_ = make_spanner ("SpacingSpanner", SCM_EOL);
110 spacing_->set_bound (LEFT,
111 unsmob_grob (get_property ("currentCommandColumn")));
115 Spacing_engraver::finalize ()
121 Spacing_engraver::stop_spanner ()
125 Grob *p = unsmob_grob (get_property ("currentCommandColumn"));
127 spacing_->set_bound (RIGHT, p);
133 Spacing_engraver::acknowledge_note_spacing (Grob_info i)
135 Pointer_group_interface::add_grob (spacing_, ly_symbol2scm ("wishes"), i.grob ());
139 Spacing_engraver::acknowledge_staff_spacing (Grob_info i)
141 Pointer_group_interface::add_grob (spacing_, ly_symbol2scm ("wishes"), i.grob ());
145 Spacing_engraver::acknowledge_rhythmic_head (Grob_info i)
147 if (i.grob ()->internal_has_interface (ly_symbol2scm ("lyric-syllable-interface"))
148 || i.grob ()->internal_has_interface (ly_symbol2scm ("multi-measure-interface")))
152 only pay attention to durations that are not grace notes.
154 if (!now_.grace_part_)
156 Music *r = i.music_cause ();
157 if (r && r->is_mus_type ("rhythmic-event"))
159 Moment len = r->get_length ();
160 Rhythmic_tuple t (i, now_mom () + len);
161 now_durations_.push_back (t);
167 Spacing_engraver::stop_translation_timestep ()
169 Paper_column *musical_column
170 = dynamic_cast<Paper_column *> (unsmob_grob (get_property ("currentMusicalColumn")));
172 SCM proportional = get_property ("proportionalNotationDuration");
173 if (unsmob_moment (proportional))
175 musical_column->set_property ("shortest-playing-duration", proportional);
176 musical_column->set_property ("shortest-starter-duration", proportional);
180 Moment shortest_playing;
181 shortest_playing.set_infinite (1);
182 for (vsize i = 0; i < playing_durations_.size (); i++)
184 Music *mus = playing_durations_[i].info_.music_cause ();
187 Moment m = mus->get_length ();
188 shortest_playing = min (shortest_playing, m);
192 starter.set_infinite (1);
194 for (vsize i = 0; i < now_durations_.size (); i++)
196 Moment m = now_durations_[i].info_.music_cause ()->get_length ();
199 starter = min (starter, m);
200 playing_durations_.insert (now_durations_[i]);
203 now_durations_.clear ();
205 shortest_playing = min (shortest_playing, starter);
207 assert (starter.to_bool ());
208 SCM sh = shortest_playing.smobbed_copy ();
209 SCM st = starter.smobbed_copy ();
211 musical_column->set_property ("shortest-playing-duration", sh);
212 musical_column->set_property ("shortest-starter-duration", st);
216 Spacing_engraver::start_translation_timestep ()
221 stopped_durations_.clear ();
223 while (playing_durations_.size () && playing_durations_.front ().end_ < now_)
224 playing_durations_.delmin ();
225 while (playing_durations_.size () && playing_durations_.front ().end_ == now_)
226 stopped_durations_.push_back (playing_durations_.get ());
229 ADD_ACKNOWLEDGER (Spacing_engraver, staff_spacing);
230 ADD_ACKNOWLEDGER (Spacing_engraver, note_spacing);
231 ADD_ACKNOWLEDGER (Spacing_engraver, rhythmic_head);
233 ADD_TRANSLATOR (Spacing_engraver,
234 "make a SpacingSpanner and do "
235 "bookkeeping of shortest starting and playing notes ",
237 /* create */ "SpacingSpanner",
239 "spacing-section-event ",
241 "currentMusicalColumn "
242 "currentCommandColumn "
243 "proportionalNotationDuration",