Fixes Issue 1504, allowing feather beam line breaking.
[lilypond/patrick.git] / lily / extender-engraver.cc
blob49fcbcaf3f598d6a55895c1238cb46685dcacd75
1 /*
2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 1999--2011 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/>.
22 #include "context.hh"
23 #include "engraver.hh"
24 #include "international.hh"
25 #include "item.hh"
26 #include "lyric-extender.hh"
27 #include "note-head.hh"
28 #include "pointer-group-interface.hh"
29 #include "stream-event.hh"
30 #include "warn.hh"
31 #include "spanner.hh"
32 #include "translator.icc"
34 void completize_extender (Spanner *sp);
36 class Extender_engraver : public Engraver
38 Stream_event *ev_;
39 Spanner *extender_;
40 Spanner *pending_extender_;
42 public:
43 TRANSLATOR_DECLARATIONS (Extender_engraver);
45 protected:
46 DECLARE_TRANSLATOR_LISTENER (extender);
47 DECLARE_TRANSLATOR_LISTENER (completize_extender);
48 DECLARE_ACKNOWLEDGER (lyric_syllable);
50 virtual void finalize ();
52 void stop_translation_timestep ();
53 void process_music ();
56 Extender_engraver::Extender_engraver ()
58 extender_ = 0;
59 pending_extender_ = 0;
60 ev_ = 0;
63 IMPLEMENT_TRANSLATOR_LISTENER (Extender_engraver, extender);
64 void
65 Extender_engraver::listen_extender (Stream_event *ev)
67 ASSIGN_EVENT_ONCE (ev_, ev);
72 A CompletizeExtenderEvent is sent at the end of each lyrics block
73 to ensure any pending extender can be correctly terminated if the lyrics
74 end before the associated voice (this prevents the right bound being extended
75 to the next note-column if no lyric follows the extender)
77 IMPLEMENT_TRANSLATOR_LISTENER (Extender_engraver, completize_extender);
78 void
79 Extender_engraver::listen_completize_extender (Stream_event * /* ev */)
81 if (pending_extender_)
83 completize_extender (pending_extender_);
84 pending_extender_ = 0;
88 void
89 Extender_engraver::process_music ()
91 if (ev_)
92 extender_ = make_spanner ("LyricExtender", ev_->self_scm ());
95 void
96 Extender_engraver::acknowledge_lyric_syllable (Grob_info i)
98 Item *item = i.item ();
99 if (extender_)
100 extender_->set_bound (LEFT, item);
102 if (pending_extender_)
104 pending_extender_->set_object ("next", item->self_scm ());
105 completize_extender (pending_extender_);
106 pending_extender_ = 0;
110 void
111 Extender_engraver::stop_translation_timestep ()
113 if (extender_ || pending_extender_)
115 Context *voice = get_voice_to_lyrics (context ());
116 Grob *h = voice ? get_current_note_head (voice, to_boolean (get_property ("includeGraceNotes"))) : 0;
118 if (h)
120 if (extender_)
122 Pointer_group_interface::add_grob (extender_,
123 ly_symbol2scm ("heads"), h);
126 if (pending_extender_)
128 Pointer_group_interface::add_grob (pending_extender_,
129 ly_symbol2scm ("heads"), h);
132 else
134 if (pending_extender_
135 && !get_property ("extendersOverRests"))
137 completize_extender (pending_extender_);
138 pending_extender_ = 0;
141 if (extender_)
143 pending_extender_ = extender_;
144 extender_ = 0;
148 ev_ = 0;
151 void
152 completize_extender (Spanner *sp)
154 if (!sp->get_bound (RIGHT))
156 extract_item_set (sp, "heads", heads);
157 if (heads.size ())
158 sp->set_bound (RIGHT, heads.back ());
162 void
163 Extender_engraver::finalize ()
165 if (extender_)
167 completize_extender (extender_);
169 if (!extender_->get_bound (RIGHT))
170 extender_->warning (_ ("unterminated extender"));
171 extender_ = 0;
174 if (pending_extender_)
176 completize_extender (pending_extender_);
178 if (!pending_extender_->get_bound (RIGHT))
179 pending_extender_->warning (_ ("unterminated extender"));
180 pending_extender_ = 0;
184 ADD_ACKNOWLEDGER (Extender_engraver, lyric_syllable);
185 ADD_TRANSLATOR (Extender_engraver,
186 /* doc */
187 "Create lyric extenders.",
189 /* create */
190 "LyricExtender ",
192 /* read */
193 "extendersOverRests "
194 "includeGraceNotes ",
196 /* write */