LEFT | RIGHT |
1 /* | 1 /* |
2 extender-engraver.cc -- implement Extender_engraver | 2 extender-engraver.cc -- implement Extender_engraver |
3 | 3 |
4 source file of the GNU LilyPond music typesetter | 4 source file of the GNU LilyPond music typesetter |
5 | 5 |
6 (c) 1999--2009 Glen Prideaux <glenprideaux@iname.com>, | 6 (c) 1999--2009 Glen Prideaux <glenprideaux@iname.com>, |
7 Han-Wen Nienhuys <hanwen@xs4all.nl>, | 7 Han-Wen Nienhuys <hanwen@xs4all.nl>, |
8 Jan Nieuwenhuizen <janneke@gnu.org> | 8 Jan Nieuwenhuizen <janneke@gnu.org> |
9 */ | 9 */ |
10 | |
11 #include "context.hh" | 10 #include "context.hh" |
12 #include "engraver.hh" | 11 #include "engraver.hh" |
13 #include "international.hh" | 12 #include "international.hh" |
14 #include "item.hh" | 13 #include "item.hh" |
15 #include "lyric-extender.hh" | 14 #include "lyric-extender.hh" |
16 #include "note-head.hh" | 15 #include "note-head.hh" |
17 #include "pointer-group-interface.hh" | 16 #include "pointer-group-interface.hh" |
18 #include "stream-event.hh" | 17 #include "stream-event.hh" |
19 #include "warn.hh" | 18 #include "warn.hh" |
20 #include "spanner.hh" | 19 #include "spanner.hh" |
| 20 #include "paper-column.hh" |
21 | 21 |
22 #include "translator.icc" | 22 #include "translator.icc" |
23 | 23 |
24 void completize_extender (Spanner *sp); | 24 void completize_extender (Spanner *sp); |
25 | 25 |
26 class Extender_engraver : public Engraver | 26 class Extender_engraver : public Engraver |
27 { | 27 { |
28 Stream_event *ev_; | 28 Stream_event *ev_; |
29 Spanner *extender_; | 29 Spanner *extender_; |
30 Spanner *pending_extender_; | 30 Spanner *pending_extender_; |
31 bool current_lyric_is_skip_; | 31 bool current_lyric_is_skip_; |
32 bool lyric_acknowledged_; | |
33 | 32 |
34 public: | 33 public: |
35 TRANSLATOR_DECLARATIONS (Extender_engraver); | 34 TRANSLATOR_DECLARATIONS (Extender_engraver); |
36 | 35 |
37 protected: | 36 protected: |
38 DECLARE_TRANSLATOR_LISTENER (extender); | 37 DECLARE_TRANSLATOR_LISTENER (extender); |
39 DECLARE_ACKNOWLEDGER (lyric_syllable); | 38 DECLARE_ACKNOWLEDGER (lyric_syllable); |
40 | 39 |
41 virtual void finalize (); | 40 virtual void finalize (); |
42 | 41 |
43 void stop_translation_timestep (); | 42 void stop_translation_timestep (); |
44 void process_music (); | 43 void process_music (); |
45 }; | 44 }; |
46 | 45 |
47 Extender_engraver::Extender_engraver () | 46 Extender_engraver::Extender_engraver () |
48 { | 47 { |
49 current_lyric_is_skip_ = false; | 48 current_lyric_is_skip_ = false; |
50 lyric_acknowledged_ = false; | |
51 extender_ = 0; | 49 extender_ = 0; |
52 pending_extender_ = 0; | 50 pending_extender_ = 0; |
53 ev_ = 0; | 51 ev_ = 0; |
54 } | 52 } |
55 | 53 |
56 IMPLEMENT_TRANSLATOR_LISTENER (Extender_engraver, extender); | 54 IMPLEMENT_TRANSLATOR_LISTENER (Extender_engraver, extender); |
57 void | 55 void |
58 Extender_engraver::listen_extender (Stream_event *ev) | 56 Extender_engraver::listen_extender (Stream_event *ev) |
59 { | 57 { |
60 ASSIGN_EVENT_ONCE (ev_, ev); | 58 ASSIGN_EVENT_ONCE (ev_, ev); |
61 } | 59 } |
62 | 60 |
63 void | 61 void |
64 Extender_engraver::process_music () | 62 Extender_engraver::process_music () |
65 { | 63 { |
66 if (ev_) | 64 if (ev_) |
67 extender_ = make_spanner ("LyricExtender", ev_->self_scm ()); | 65 extender_ = make_spanner ("LyricExtender", ev_->self_scm ()); |
68 } | 66 } |
69 | 67 |
70 void | 68 void |
71 Extender_engraver::acknowledge_lyric_syllable (Grob_info i) | 69 Extender_engraver::acknowledge_lyric_syllable (Grob_info i) |
72 { | 70 { |
73 lyric_acknowledged_ = true; | |
74 Item *item = i.item (); | 71 Item *item = i.item (); |
75 if (extender_) | 72 if (extender_) |
76 extender_->set_bound (LEFT, item); | 73 extender_->set_bound (LEFT, item); |
77 | 74 |
78 SCM text = item->get_property ("text"); | 75 SCM text = item->get_property ("text"); |
79 current_lyric_is_skip_ = ly_is_equal (text, scm_from_locale_string (" ")); | 76 current_lyric_is_skip_ = ly_is_equal (text, scm_from_locale_string (" ")); |
80 | 77 |
81 if (pending_extender_ && !current_lyric_is_skip_) | 78 if (pending_extender_ && !current_lyric_is_skip_) |
82 { | 79 { |
83 pending_extender_->set_object ("next", item->self_scm ()); | 80 pending_extender_->set_object ("next", item->self_scm ()); |
(...skipping 11 matching lines...) Expand all Loading... |
95 Grob *h = voice ? get_current_note_head (voice) : 0; | 92 Grob *h = voice ? get_current_note_head (voice) : 0; |
96 | 93 |
97 if (h) | 94 if (h) |
98 { | 95 { |
99 if (extender_) | 96 if (extender_) |
100 { | 97 { |
101 Pointer_group_interface::add_grob (extender_, | 98 Pointer_group_interface::add_grob (extender_, |
102 ly_symbol2scm ("heads"), h); | 99 ly_symbol2scm ("heads"), h); |
103 } | 100 } |
104 | 101 |
105 » if (pending_extender_) | 102 if (pending_extender_) |
106 » { | 103 { |
107 » Pointer_group_interface::add_grob (pending_extender_, | 104 Pointer_group_interface::add_grob (pending_extender_, |
108 » » » » » » ly_symbol2scm ("heads"), h); | 105 ly_symbol2scm ("heads"), h); |
109 if (!melisma_busy (voice) && !current_lyric_is_skip_ && lyric_ackno
wledged_) | 106 /* |
110 { | 107 The following check addresses the case where the lyrics end before |
111 completize_extender (pending_extender_); | 108 the associated voice. The current_lyric_is_skip_ check is |
112 pending_extender_ = 0; | 109 necessary to handle manual melismata, which should not result in |
113 } | 110 extenders being completized. We also need to make sure that we're
not |
114 » } | 111 in the middle of a note (happens when this function is called beca
use |
115 » } | 112 of an event in a voice other than our associated one). |
| 113 */ |
| 114 if (!melisma_busy (voice) && !current_lyric_is_skip_) |
| 115 { |
| 116 Moment now = voice->now_mom (); |
| 117 Paper_column *column = (dynamic_cast<Item *> (h))->get_column ()
; |
| 118 Moment *start_mom = column ? unsmob_moment (column->get_property
("when")) : 0; |
| 119 if (!column || (start_mom->main_part_ == now.main_part_)) |
| 120 { |
| 121 completize_extender (pending_extender_); |
| 122 pending_extender_ = 0; |
| 123 } |
| 124 } |
| 125 } |
| 126 } |
116 else | 127 else |
117 { | 128 { |
118 if (pending_extender_ | 129 if (pending_extender_ |
119 && !get_property ("extendersOverRests")) | 130 && !get_property ("extendersOverRests")) |
120 { | 131 { |
121 completize_extender (pending_extender_); | 132 completize_extender (pending_extender_); |
122 pending_extender_ = 0; | 133 pending_extender_ = 0; |
123 } | 134 } |
124 ·········· | 135 ·········· |
125 } | 136 } |
126 if (extender_) | 137 if (extender_) |
127 { | 138 { |
128 pending_extender_ = extender_; | 139 pending_extender_ = extender_; |
129 extender_ = 0; | 140 extender_ = 0; |
130 } | 141 } |
131 } | 142 } |
132 | 143 |
133 ev_ = 0; | 144 ev_ = 0; |
134 lyric_acknowledged_ = false; | |
135 } | 145 } |
136 | 146 |
137 void | 147 void |
138 completize_extender (Spanner *sp) | 148 completize_extender (Spanner *sp) |
139 { | 149 { |
140 if (!sp->get_bound (RIGHT)) | 150 if (!sp->get_bound (RIGHT)) |
141 { | 151 { |
142 extract_item_set (sp, "heads", heads); | 152 extract_item_set (sp, "heads", heads); |
143 if (heads.size ()) | 153 if (heads.size ()) |
144 sp->set_bound (RIGHT, heads.back ()); | 154 sp->set_bound (RIGHT, heads.back ()); |
(...skipping 29 matching lines...) Expand all Loading... |
174 | 184 |
175 /* create */ | 185 /* create */ |
176 "LyricExtender ", | 186 "LyricExtender ", |
177 | 187 |
178 /* read */ | 188 /* read */ |
179 "extendersOverRests ", | 189 "extendersOverRests ", |
180 | 190 |
181 /* write */ | 191 /* write */ |
182 "" | 192 "" |
183 ); | 193 ); |
LEFT | RIGHT |