]> git.donarmstrong.com Git - lilypond.git/blob - lily/extender-engraver.cc
Merge commit 'origin'
[lilypond.git] / lily / extender-engraver.cc
1 /*
2   extender-engraver.cc -- implement Extender_engraver
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1999--2009 Glen Prideaux <glenprideaux@iname.com>,
7   Han-Wen Nienhuys <hanwen@xs4all.nl>,
8   Jan Nieuwenhuizen <janneke@gnu.org>
9 */
10
11 #include "context.hh"
12 #include "engraver.hh"
13 #include "international.hh"
14 #include "item.hh"
15 #include "lyric-extender.hh"
16 #include "note-head.hh"
17 #include "pointer-group-interface.hh"
18 #include "stream-event.hh"
19 #include "warn.hh"
20 #include "spanner.hh"
21
22 #include "translator.icc"
23
24 void completize_extender (Spanner *sp);
25
26 class Extender_engraver : public Engraver
27 {
28   Stream_event *ev_;
29   Spanner *extender_;
30   Spanner *pending_extender_;
31
32 public:
33   TRANSLATOR_DECLARATIONS (Extender_engraver);
34
35 protected:
36   DECLARE_TRANSLATOR_LISTENER (extender);
37   DECLARE_ACKNOWLEDGER (lyric_syllable);
38
39   virtual void finalize ();
40
41   void stop_translation_timestep ();
42   void process_music ();
43 };
44
45 Extender_engraver::Extender_engraver ()
46 {
47   extender_ = 0;
48   pending_extender_ = 0;
49   ev_ = 0;
50 }
51
52 IMPLEMENT_TRANSLATOR_LISTENER (Extender_engraver, extender);
53 void
54 Extender_engraver::listen_extender (Stream_event *ev)
55 {
56   ASSIGN_EVENT_ONCE (ev_, ev);
57 }
58
59 void
60 Extender_engraver::process_music ()
61 {
62   if (ev_)
63     extender_ = make_spanner ("LyricExtender", ev_->self_scm ());
64 }
65
66 void
67 Extender_engraver::acknowledge_lyric_syllable (Grob_info i)
68 {
69   Item *item = i.item ();
70   if (extender_)
71     extender_->set_bound (LEFT, item);
72
73   if (pending_extender_)
74     {
75       pending_extender_->set_object ("next", item->self_scm ());
76       completize_extender (pending_extender_);
77       pending_extender_ = 0;
78     }
79 }
80
81 void
82 Extender_engraver::stop_translation_timestep ()
83 {
84   if (extender_ || pending_extender_)
85     {
86       Context *voice = get_voice_to_lyrics (context ());
87       Grob *h = voice ? get_current_note_head (voice) : 0;
88
89       if (h)
90         {
91           if (extender_)
92             {
93               Pointer_group_interface::add_grob (extender_,
94                                                  ly_symbol2scm ("heads"), h);
95             }
96
97           if (pending_extender_)
98             {
99               Pointer_group_interface::add_grob (pending_extender_,
100                                                  ly_symbol2scm ("heads"), h);
101              if (!melisma_busy (voice))
102                {
103                  completize_extender (pending_extender_);
104                  pending_extender_ = 0;
105                }
106             }
107         }
108       else
109         {
110           if (pending_extender_
111               && !get_property ("extendersOverRests"))
112             {
113               completize_extender (pending_extender_);
114               pending_extender_ = 0;
115             }
116           
117         }
118       if (extender_)
119         {
120           pending_extender_ = extender_;
121           extender_ = 0;
122         }
123     }
124
125   ev_ = 0;
126 }
127
128 void
129 completize_extender (Spanner *sp)
130 {
131   if (!sp->get_bound (RIGHT))
132     {
133       extract_item_set (sp, "heads", heads);
134       if (heads.size ())
135         sp->set_bound (RIGHT, heads.back ());
136     }
137 }
138
139 void
140 Extender_engraver::finalize ()
141 {
142   if (extender_)
143     {
144       completize_extender (extender_);
145
146       if (!extender_->get_bound (RIGHT))
147         extender_->warning (_ ("unterminated extender"));
148       extender_ = 0;
149     }
150
151   if (pending_extender_)
152     {
153       completize_extender (pending_extender_);
154
155       if (!pending_extender_->get_bound (RIGHT))
156         pending_extender_->warning (_ ("unterminated extender"));
157       pending_extender_ = 0;
158     }
159 }
160
161 ADD_ACKNOWLEDGER (Extender_engraver, lyric_syllable);
162 ADD_TRANSLATOR (Extender_engraver,
163                 /* doc */
164                 "Create lyric extenders.",
165
166                 /* create */
167                 "LyricExtender ",
168
169                 /* read */
170                 "extendersOverRests ",
171
172                 /* write */
173                 ""
174                 );