2 new-phrasing-engraver.cc -- implement New_phrasing_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 2003--2004 Han-Wen Nienhuys <hanwen@xs4all.nl>
12 #include "engraver.hh"
13 #include "note-head.hh"
14 #include "lyric-extender.hh"
16 #include "group-interface.hh"
17 #include "side-position-interface.hh"
19 struct Phrasing_association
22 Link_array<Grob> lyrics_;
23 Link_array<Grob> heads_;
24 Link_array<Spanner> past_extenders_;
25 Link_array<Spanner> new_extenders_;
26 Link_array<Grob> stanza_numbers_;
31 Phrasing_association()
37 class Lyric_phrasing_engraver : public Engraver
40 ~Lyric_phrasing_engraver ();
41 TRANSLATOR_DECLARATIONS(Lyric_phrasing_engraver);
43 virtual void acknowledge_grob (Grob_info);
44 virtual void process_acknowledged_grobs ();
45 virtual void stop_translation_timestep ();
48 void add_lyric_phrasing (Grob_info);
49 void add_voice_phrasing (Grob_info);
50 void add_lyric_extender (Grob_info);
51 void add_stanza_number (Grob_info);
52 Phrasing_association *get_phrasing_assoc (String nm);
53 String get_voice_name_for_lyric (Context *tr);
54 Link_array<Phrasing_association> assocs_;
57 Lyric_phrasing_engraver::Lyric_phrasing_engraver()
62 Lyric_phrasing_engraver::acknowledge_grob (Grob_info i)
66 if (Note_head::has_interface (h))
67 add_voice_phrasing (i);
68 else if (h->internal_has_interface (ly_symbol2scm ("lyric-syllable-interface")))
69 add_lyric_phrasing (i);
70 else if (Lyric_extender::has_interface (h))
71 add_lyric_extender (i);
72 else if (h->internal_has_interface (ly_symbol2scm ("stanza-number-interface")))
73 add_stanza_number (i);
76 Phrasing_association *
77 Lyric_phrasing_engraver::get_phrasing_assoc (String nm)
79 Phrasing_association * a=0;
80 for (int i=0 ; !a && i < assocs_.size (); i++)
82 if (assocs_[i]->name_ == nm)
88 a = new Phrasing_association ;
98 Lyric_phrasing_engraver::get_voice_name_for_lyric (Context *tr)
100 SCM voice_context = tr->get_property ("associatedVoiceContext");
101 if (Context *vc = unsmob_context (voice_context))
103 return vc->id_string_;
106 SCM voice = tr->get_property ("associatedVoice");
107 String nm = tr->id_string_;
108 if (gh_string_p (voice))
109 nm = ly_scm2string (voice);
112 int idx = nm.index_last ('-');
114 nm = nm.left_string (idx);
122 Lyric_phrasing_engraver::add_lyric_extender (Grob_info inf)
124 Context * tr = inf.origin_trans_->daddy_context_;
125 while (tr && !tr->is_alias (ly_symbol2scm ("Lyrics")))
126 tr = tr->daddy_context_;
132 Phrasing_association *a = get_phrasing_assoc (get_voice_name_for_lyric (tr));
133 a->new_extenders_.push (dynamic_cast<Spanner*> (inf.grob_));
137 Lyric_phrasing_engraver::add_stanza_number (Grob_info inf)
139 Context * tr = inf.origin_trans_->daddy_context_;
140 while (tr && !tr->is_alias (ly_symbol2scm ("Lyrics")))
141 tr = tr->daddy_context_;
146 Phrasing_association *a = get_phrasing_assoc (get_voice_name_for_lyric (tr));
147 a->stanza_numbers_.push (inf.grob_);
151 Lyric_phrasing_engraver::add_voice_phrasing (Grob_info inf)
153 Context * tr = inf.origin_trans_->daddy_context_;
154 while (tr && !tr->is_alias (ly_symbol2scm ("Voice")))
155 tr = tr->daddy_context_;
160 Phrasing_association *a = get_phrasing_assoc (tr->id_string_);
161 a->heads_.push (inf.grob_);
162 a->melisma_ = melisma_busy (inf.origin_trans_);
166 Lyric_phrasing_engraver::add_lyric_phrasing (Grob_info inf)
168 Context * tr = inf.origin_trans_->daddy_context_;
169 while (tr && !tr->is_alias (ly_symbol2scm ("Lyrics")))
170 tr = tr->daddy_context_;
176 Phrasing_association *a = get_phrasing_assoc (get_voice_name_for_lyric (tr));
177 a->lyrics_.push (inf.grob_);
178 a->past_extenders_.clear ();
182 Lyric_phrasing_engraver::stop_translation_timestep ()
184 Link_array<Grob> stzs;
185 Link_array<Grob> lyrs;
186 for (int i = assocs_.size (); i--; )
188 Phrasing_association * a = assocs_[i];
189 stzs.concat (a->stanza_numbers_);
190 lyrs.concat (a->lyrics_);
193 for(int i= lyrs.size(); i--;)
194 for (int j = stzs.size (); j--;)
195 Side_position_interface::add_support (stzs[j], lyrs[i]);
197 for (int i = assocs_.size (); i--; )
199 Phrasing_association * a = assocs_[i];
201 a->stanza_numbers_.clear ();
204 a->past_extenders_.concat (assocs_[i]->new_extenders_) ;
205 a->new_extenders_.clear ();
210 Lyric_phrasing_engraver::process_acknowledged_grobs ()
212 for (int i = 0; i < assocs_.size (); i++)
214 Phrasing_association * a = assocs_[i];
215 if (! (a->heads_.size() && (a->lyrics_.size () || a->past_extenders_.size ())))
218 Grob *h = a->heads_[0];
219 Direction alignment = CENTER;
223 for (int j = 0; j < a->lyrics_.size (); j++)
225 Grob *l = a->lyrics_[j];
226 if (!l->get_parent (X_AXIS))
228 l->set_parent (h, X_AXIS);
230 l->set_grob_property ("self-alignment-X", gh_int2scm (alignment));
234 for (int j = a->past_extenders_.size(); j--;)
235 Pointer_group_interface::add_grob (a->past_extenders_[j],ly_symbol2scm ("heads"), h);
239 Lyric_phrasing_engraver::~Lyric_phrasing_engraver ()
241 for (int i =assocs_.size(); i--;)
245 ENTER_DESCRIPTION(Lyric_phrasing_engraver,
246 "This engraver combines note heads and lyrics for alignment. ",
249 "stanza-number-interface lyric-syllable-interface "
250 "note-head-interface lyric-extender-interface",