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>
11 #include "translator-group.hh"
12 #include "engraver.hh"
13 #include "note-head.hh"
14 #include "lyric-extender.hh"
16 #include "group-interface.hh"
18 struct Phrasing_association
21 Link_array<Grob> lyrics_;
22 Link_array<Grob> heads_;
23 Link_array<Spanner> past_extenders_;
24 Link_array<Spanner> new_extenders_;
28 Phrasing_association()
34 class Lyric_phrasing_engraver : public Engraver
37 ~Lyric_phrasing_engraver ();
38 TRANSLATOR_DECLARATIONS(Lyric_phrasing_engraver);
40 virtual void acknowledge_grob (Grob_info);
41 virtual void process_acknowledged_grobs ();
42 virtual void stop_translation_timestep ();
45 void add_lyric_phrasing (Grob_info);
46 void add_voice_phrasing (Grob_info);
47 void add_lyric_extender (Grob_info);
48 Phrasing_association *get_phrasing_assoc (String nm);
49 String get_voice_name_for_lyric (Translator_group*tr);
50 Link_array<Phrasing_association> assocs_;
53 Lyric_phrasing_engraver::Lyric_phrasing_engraver()
58 Lyric_phrasing_engraver::acknowledge_grob (Grob_info i)
62 if (Note_head::has_interface (h))
63 add_voice_phrasing (i);
64 else if (h->internal_has_interface (ly_symbol2scm ("lyric-syllable-interface")))
65 add_lyric_phrasing (i);
66 else if (Lyric_extender::has_interface (h))
67 add_lyric_extender (i);
70 Phrasing_association *
71 Lyric_phrasing_engraver::get_phrasing_assoc (String nm)
73 Phrasing_association * a=0;
74 for (int i=0 ; !a && i < assocs_.size (); i++)
76 if (assocs_[i]->name_ == nm)
82 a = new Phrasing_association ;
92 Lyric_phrasing_engraver::get_voice_name_for_lyric (Translator_group*tr)
94 SCM voice_context = tr->get_property ("associatedVoiceContext");
95 if (Translator *vc = unsmob_translator (voice_context))
97 return dynamic_cast<Translator_group*> (vc)->id_string_;
100 SCM voice = tr->get_property ("associatedVoice");
101 String nm = tr->id_string_;
102 if (gh_string_p (voice))
103 nm = ly_scm2string (voice);
106 int idx = nm.index_last ('-');
108 nm = nm.left_string (idx);
116 Lyric_phrasing_engraver::add_lyric_extender (Grob_info inf)
118 Translator_group * tr = inf.origin_trans_->daddy_trans_;
119 while (tr && !tr->is_alias (ly_symbol2scm ("LyricsVoice")))
120 tr = tr->daddy_trans_;
126 Phrasing_association *a = get_phrasing_assoc (get_voice_name_for_lyric (tr));
127 a->new_extenders_.push (dynamic_cast<Spanner*> (inf.grob_));
132 Lyric_phrasing_engraver::add_voice_phrasing (Grob_info inf)
134 Translator_group * tr = inf.origin_trans_->daddy_trans_;
135 while (tr && !tr->is_alias (ly_symbol2scm ("Voice")))
136 tr = tr->daddy_trans_;
141 Phrasing_association *a = get_phrasing_assoc (tr->id_string_);
142 a->heads_.push (inf.grob_);
143 a->melisma_ = melisma_busy (inf.origin_trans_);
147 Lyric_phrasing_engraver::add_lyric_phrasing (Grob_info inf)
149 Translator_group * tr = inf.origin_trans_->daddy_trans_;
150 while (tr && !tr->is_alias (ly_symbol2scm ("LyricsVoice")))
151 tr = tr->daddy_trans_;
157 Phrasing_association *a = get_phrasing_assoc (get_voice_name_for_lyric (tr));
158 a->lyrics_.push (inf.grob_);
159 a->past_extenders_.clear ();
163 Lyric_phrasing_engraver::stop_translation_timestep ()
165 for (int i = assocs_.size (); i--; )
167 assocs_[i]->heads_.clear ();
168 assocs_[i]->lyrics_.clear ();
169 assocs_[i]->past_extenders_.concat (assocs_[i]->new_extenders_) ;
170 assocs_[i]->new_extenders_.clear ();
175 Lyric_phrasing_engraver::process_acknowledged_grobs ()
177 for (int i = 0; i < assocs_.size (); i++)
179 Phrasing_association * a = assocs_[i];
180 if (! (a->heads_.size() && (a->lyrics_.size () || a->past_extenders_.size ())))
183 Grob *h = a->heads_[0];
184 Direction alignment = CENTER;
188 for (int j = 0; j < a->lyrics_.size (); j++)
190 Grob *l = a->lyrics_[j];
191 if (!l->get_parent (X_AXIS))
193 l->set_parent (h, X_AXIS);
195 l->set_grob_property ("self-alignment-X", gh_int2scm (alignment));
199 for (int j = a->past_extenders_.size(); j--;)
200 Pointer_group_interface::add_grob (a->past_extenders_[j],ly_symbol2scm ("heads"), h);
204 Lyric_phrasing_engraver::~Lyric_phrasing_engraver ()
206 for (int i =assocs_.size(); i--;)
210 ENTER_DESCRIPTION(Lyric_phrasing_engraver,
211 "This engraver combines note heads and lyrics for alignment. ",
214 "lyric-syllable-interface note-head-interface lyric-extender-interface",