Lyric_phrasing_engraver::Lyric_phrasing_engraver()
{
voice_alist_ = SCM_EOL;
+ any_notehead_l_ = 0;
}
Lyric_phrasing_engraver::~Lyric_phrasing_engraver()
{
Voice_alist_entry * v = lookup_context_id(context_id);
v->set_notehead(notehead);
- // voice_alist_ =
- // scm_assoc_set_x(voice_alist_, ly_str02scm(context_id.ch_C()), smobify(v));
+ if(!any_notehead_l_)
+ any_notehead_l_ = notehead;
}
void
{
Voice_alist_entry * v = lookup_context_id(context_id);
v->add_lyric(lyric);
- // voice_alist_ =
- // scm_assoc_set_x(voice_alist_, ly_str02scm(context_id.ch_C()), smobify(v));
}
*/
Voice_alist_entry *entry;
String punc;
- if (punc.empty_b()) {
- SCM sp = get_property("phrasingPunctuation");
- punc = gh_string_p(sp) ? ly_scm2string(sp) : ".,;?!";
- }
-
+ SCM sp = get_property("phrasingPunctuation");
+ punc = gh_string_p(sp) ? ly_scm2string(sp) : ".,;:?!\"";
+
for(unsigned v=0; v < gh_length(voice_alist_); v++) {
entry = unsmob_voice_entry(gh_cdr(gh_list_ref(voice_alist_, gh_int2scm(v))));
- if(! entry->set_lyric_align(punc.ch_C()))
- warning (_ ("lyrics found without matching notehead ... aligning on self"));
+ if(! entry->set_lyric_align(punc.ch_C(), any_notehead_l_))
+ warning (_ ("lyrics found without any matching notehead"));
}
}
entry = unsmob_voice_entry(gh_cdr(gh_list_ref(voice_alist_, gh_int2scm(v))));
entry->next_lyric();
}
+ any_notehead_l_ = 0;
}
{
notehead_l_=0;
lyric_list_.clear();
- longest_lyric_=-1;
- shortest_lyric_=-1;
+ longest_lyric_l_=0;
+ shortest_lyric_l_=0;
}
void
void
Voice_alist_entry::add_lyric(Score_element * lyric)
{
- int this_lyric = lyric_list_.size();
lyric_list_.push(lyric);
/* record longest and shortest lyrics */
- if(longest_lyric_>-1) {
- Real this_length = (lyric->extent(X_AXIS)).length();
- if(this_length > (lyric_list_[longest_lyric_]->extent(X_AXIS)).length())
- longest_lyric_ = this_lyric;
- if(this_length < (lyric_list_[shortest_lyric_]->extent(X_AXIS)).length())
- shortest_lyric_ = this_lyric;
+ if( longest_lyric_l_ ) {
+ if(lyric->extent(X_AXIS).length() > (longest_lyric_l_->extent(X_AXIS)).length())
+ longest_lyric_l_ = lyric;
+ if(lyric->extent(X_AXIS).length() < (shortest_lyric_l_->extent(X_AXIS)).length())
+ shortest_lyric_l_ = lyric;
}
else
- longest_lyric_ = shortest_lyric_ = this_lyric;
+ longest_lyric_l_ = shortest_lyric_l_ = lyric;
}
bool
-Voice_alist_entry::set_lyric_align(const char *punc)
+Voice_alist_entry::set_lyric_align(const char *punc, Score_element *default_notehead_l)
{
if(lyric_list_.size()<2) {
/* Only for multi-stanza songs ... if we've only a single lyric (or none at all) we
lyric = lyric_list_[l];
lyric->set_elt_property("self-alignment-X", gh_int2scm(alignment_i_));
- // centre on notehead
-
- if(notehead_l_) {
+ // centre on notehead ... if we have one. If there was no notehead in the matching
+ // voice context, use the first notehead caught from any voice context (any port in a storm).
+ if(notehead_l_ || default_notehead_l) {
/* set the parent of each lyric to the notehead,
set the offset callback of each lyric to centered_on_parent,
*/
- lyric->set_parent(notehead_l_, X_AXIS);
+ Score_element * parent_nh = notehead_l_ ? notehead_l_ : default_notehead_l;
+ lyric->set_parent(parent_nh, X_AXIS);
lyric->add_offset_callback (Side_position::centered_on_parent, X_AXIS);
/* reference is on the right of the notehead; move it left half way */
- lyric->translate_axis (-(notehead_l_->extent(X_AXIS)).center(), X_AXIS);
- }
- else {
- /* No matching notehead: just align to the first lyric, and
- issue a warning about lyric without matching notehead
- */
- if(l) {
- lyric->set_parent(lyric_list_[0], X_AXIS);
- lyric->add_offset_callback (Side_position::centered_on_parent, X_AXIS);
- }
- else
- lyric->add_offset_callback (Side_position::aligned_on_self, X_AXIS);
- }
-
- if(alignment_i_ != CENTER) {
- // right or left align ...
- /* If length of longest lyric < 2 * length of shortest lyric,
- - centre longest lyric on notehead
- Otherwise
- - move so shortest lyric just reaches notehead centre
- */
- // FIXME: do we really know the lyric extent here? Some font sizing comes later?
- Real translate;
- if((lyric_list_[longest_lyric_]->extent(X_AXIS)).length() <
- (lyric_list_[shortest_lyric_]->extent(X_AXIS)).length() * 2 )
- translate = alignment_i_*(lyric_list_[longest_lyric_]->extent(X_AXIS)).length()/2;
- else
- translate = alignment_i_*(lyric_list_[shortest_lyric_]->extent(X_AXIS)).length();
- lyric->translate_axis (translate, X_AXIS);
+ lyric->translate_axis (-(parent_nh->extent(X_AXIS)).center(), X_AXIS);
+
+ if(alignment_i_ != CENTER) {
+ // right or left align ...
+ /* If length of longest lyric < 2 * length of shortest lyric,
+ - centre longest lyric on notehead
+ Otherwise
+ - move so shortest lyric just reaches notehead centre
+ */
+ // FIXME: do we really know the lyric extent here? Some font sizing comes later?
+ Real translate;
+ if((longest_lyric_l_->extent(X_AXIS)).length() <
+ (shortest_lyric_l_->extent(X_AXIS)).length() * 2 )
+ translate = alignment_i_*(longest_lyric_l_->extent(X_AXIS)).length()/2;
+ else
+ translate = alignment_i_*(shortest_lyric_l_->extent(X_AXIS)).length();
+ lyric->translate_axis (translate, X_AXIS);
}
}
-
- return (notehead_l_ != 0);
+ }
+ return (notehead_l_ || default_notehead_l);
}
/** determine what alignment we want.
--- /dev/null
+
+/*
+ lyric-number-engraver.cc -- implement Stanza_number_engraver
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>, Glen Prideaux <glenprideaux@iname.com>
+
+ Similar to (and derived from) Instrument_name_engraver.
+ */
+
+#include "engraver.hh"
+#include "item.hh"
+//#include "system-start-delimiter.hh"
+//#include "side-position-interface.hh"
+//#include "staff-symbol-referencer.hh"
+#include "bar.hh"
+
+class Stanza_number_engraver : public Engraver
+{
+ Item *text_;
+ bool bar_b_;;
+
+ void create_text (SCM s);
+public:
+ VIRTUAL_COPY_CONS(Translator);
+ Stanza_number_engraver ();
+
+ virtual void acknowledge_element (Score_element_info);
+ virtual void do_pre_move_processing ();
+};
+
+ADD_THIS_TRANSLATOR(Stanza_number_engraver);
+
+Stanza_number_engraver::Stanza_number_engraver ()
+{
+ text_ = 0;
+ bar_b_ = false;
+}
+
+void
+Stanza_number_engraver::acknowledge_element(Score_element_info i)
+{
+ SCM s = get_property ("stanza");
+
+ if (now_mom () > Moment (0))
+ s = get_property ("stz");
+
+ if (gh_string_p (s))
+ {
+// if (i.elem_l_->has_interface (ly_symbol2scm ("lyric-syllable-interface")))
+ // Tried catching lyric items to generate stanza numbers, but it spoils lyric spacing.
+ if (Bar::has_interface (i.elem_l_) || now_mom() == Moment(0))
+ // Works, but requires bar_engraver in LyricVoice context apart from at beginning.
+ // Is there any score element we can catch that will do the trick?
+// if (! i.elem_l_->has_interface (ly_symbol2scm ("lyric-syllable-interface")) ||
+// now_mom() == Moment(0))
+ // What happens if we try anything at all EXCEPT a lyric? Is there anything else?
+ // Not sure what it's catching, but it still mucks up lyrics.
+ create_text (s);
+ }
+}
+
+
+void
+Stanza_number_engraver::do_pre_move_processing ()
+{
+ if (text_)
+ {
+ typeset_element (text_);
+ text_ = 0;
+ }
+}
+
+void
+Stanza_number_engraver::create_text (SCM txt)
+{
+ if(!text_)
+ {
+ text_ = new Item (get_property ("basicStanzaNumberProperties"));
+ text_->set_elt_property ("text", txt);
+ announce_element (text_,0);
+ }
+}
+
+
+
+
\consists "Lyric_engraver";
\consists "Extender_engraver";
\consists "Hyphen_engraver";
-
- phrasingPunctuation = #".,;:!?"
+ \consists "Stanza_number_engraver";
+ phrasingPunctuation = #".,;:!?\""
+
};
\translator{ \LyricsVoiceContext }
Key_item
Staff_bar
Time_signature
+ Stanza_number
)
\consists "Spacing_engraver";
\consists "Vertical_align_engraver";
\consists "Lyric_phrasing_engraver";
- automaticPhrasing = ##f;
+ automaticPhrasing = ##t;
\consists "Bar_number_engraver";
alignmentReference = \down;
(molecule-callback . ,Volta_spanner::brew_molecule)
(interfaces . (volta-spanner-interface))
)
+ basicStanzaNumberProperties = #`(
+ (breakable . #t)
+ (molecule-callback . ,Text_item::brew_molecule)
+ (break-align-symbol . Clef_item)
+ (visibility-lambda . ,begin-of-line-visible)
+ )
\accepts "Staff";
\accepts "StaffGroup";