2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 1999--2015 Glen Prideaux <glenprideaux@iname.com>,
5 Han-Wen Nienhuys <hanwen@xs4all.nl>,
6 Jan Nieuwenhuizen <janneke@gnu.org>
8 LilyPond is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 LilyPond is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
23 #include "engraver.hh"
24 #include "international.hh"
26 #include "lyric-extender.hh"
27 #include "note-head.hh"
28 #include "pointer-group-interface.hh"
29 #include "stream-event.hh"
32 #include "translator.icc"
34 void completize_extender (Spanner *sp);
36 class Extender_engraver : public Engraver
40 Spanner *pending_extender_;
43 TRANSLATOR_DECLARATIONS (Extender_engraver);
46 void listen_extender (Stream_event *);
47 void listen_completize_extender (Stream_event *);
48 void acknowledge_lyric_syllable (Grob_info);
50 virtual void finalize ();
52 void stop_translation_timestep ();
53 void process_music ();
56 Extender_engraver::Extender_engraver ()
59 pending_extender_ = 0;
64 Extender_engraver::listen_extender (Stream_event *ev)
66 ASSIGN_EVENT_ONCE (ev_, ev);
70 A CompletizeExtenderEvent is sent at the end of each lyrics block
71 to ensure any pending extender can be correctly terminated if the lyrics
72 end before the associated voice (this prevents the right bound being extended
73 to the next note-column if no lyric follows the extender)
76 Extender_engraver::listen_completize_extender (Stream_event * /* ev */)
78 if (pending_extender_)
80 completize_extender (pending_extender_);
81 pending_extender_ = 0;
86 Extender_engraver::process_music ()
89 extender_ = make_spanner ("LyricExtender", ev_->self_scm ());
93 Extender_engraver::acknowledge_lyric_syllable (Grob_info i)
95 Item *item = i.item ();
97 extender_->set_bound (LEFT, item);
99 if (pending_extender_)
101 pending_extender_->set_object ("next", item->self_scm ());
102 completize_extender (pending_extender_);
103 pending_extender_ = 0;
108 Extender_engraver::stop_translation_timestep ()
110 if (extender_ || pending_extender_)
112 Context *voice = get_voice_to_lyrics (context ());
113 Grob *h = voice ? get_current_note_head (voice) : 0;
119 Pointer_group_interface::add_grob (extender_,
120 ly_symbol2scm ("heads"), h);
123 if (pending_extender_)
125 Pointer_group_interface::add_grob (pending_extender_,
126 ly_symbol2scm ("heads"), h);
131 if (pending_extender_
132 && !get_property ("extendersOverRests"))
134 completize_extender (pending_extender_);
135 pending_extender_ = 0;
140 pending_extender_ = extender_;
149 completize_extender (Spanner *sp)
151 if (!sp->get_bound (RIGHT))
153 extract_item_set (sp, "heads", heads);
155 sp->set_bound (RIGHT, heads.back ());
160 Extender_engraver::finalize ()
164 completize_extender (extender_);
166 if (!extender_->get_bound (RIGHT))
167 extender_->warning (_ ("unterminated extender"));
171 if (pending_extender_)
173 completize_extender (pending_extender_);
175 if (!pending_extender_->get_bound (RIGHT))
176 pending_extender_->warning (_ ("unterminated extender"));
177 pending_extender_ = 0;
182 Extender_engraver::boot ()
184 ADD_LISTENER (Extender_engraver, extender);
185 ADD_LISTENER (Extender_engraver, completize_extender);
186 ADD_ACKNOWLEDGER (Extender_engraver, lyric_syllable);
189 ADD_TRANSLATOR (Extender_engraver,
191 "Create lyric extenders.",
197 "extendersOverRests ",