#include "paper-def.hh"
-/*=========================================================================================*/
-
-/** Syllable_group is a class to be smobbed and entered as data in the association list
- member of the Lyric_phrasing_engraver class.
+/*
+ Syllable_group is a class to be smobbed and entered as data in the
+ association list member of the Lyric_phrasing_engraver class.
*/
Syllable_group::Syllable_group ()
void
Syllable_group::clear ()
{
- notehead_l_=0;
- lyric_list_.clear ();
- longest_lyric_l_=0;
- shortest_lyric_l_=0;
+ notehead_=0;
+ lyrics_.clear ();
+ longest_lyric_=0;
+ shortest_lyric_=0;
melisma_b_ = false;
- group_translation_f_ = 0.0;
+ group_translation_ = 0.0;
}
void
Syllable_group::copy (Syllable_group *from)
{
- notehead_l_ = from->notehead_l_;
- lyric_list_ = from->lyric_list_;
- longest_lyric_l_ = from->longest_lyric_l_;
- shortest_lyric_l_ = from->shortest_lyric_l_;
+ notehead_ = from->notehead_;
+ lyrics_ = from->lyrics_;
+ longest_lyric_ = from->longest_lyric_;
+ shortest_lyric_ = from->shortest_lyric_;
melisma_b_ = from->melisma_b_;
- alignment_i_ = from->alignment_i_;
+ alignment_ = from->alignment_;
first_in_phrase_b_ = from->first_in_phrase_b_;
- group_translation_f_ = from->group_translation_f_;
+ group_translation_ = from->group_translation_;
}
void
void
Syllable_group::set_notehead (Grob * notehead)
{
- if (!notehead_l_) {
- /* there should only be a single notehead, so silently ignore any extras */
- notehead_l_=notehead;
- }
+ if (!notehead_)
+ {
+ /* there should only be a single notehead, so silently ignore
+ any extras */
+ notehead_=notehead;
+ }
}
void
Syllable_group::add_lyric (Grob * lyric)
{
- lyric_list_.push (lyric);
+ lyrics_.push (lyric);
/* record longest and shortest lyrics */
- if (longest_lyric_l_) {
- if (lyric->extent (lyric,X_AXIS).length () > (longest_lyric_l_->extent (longest_lyric_l_, X_AXIS)).length ())
- longest_lyric_l_ = lyric;
- if (lyric->extent (lyric, X_AXIS).length () < (shortest_lyric_l_->extent (shortest_lyric_l_, X_AXIS)).length ())
- shortest_lyric_l_ = lyric;
- }
+ if (longest_lyric_)
+ {
+ if (lyric->extent (lyric,X_AXIS).length () > (longest_lyric_->extent (longest_lyric_, X_AXIS)).length ())
+ longest_lyric_ = lyric;
+ if (lyric->extent (lyric, X_AXIS).length () < (shortest_lyric_->extent (shortest_lyric_, X_AXIS)).length ())
+ shortest_lyric_ = lyric;
+ }
else
- longest_lyric_l_ = shortest_lyric_l_ = lyric;
+ longest_lyric_ = shortest_lyric_ = lyric;
}
void
Syllable_group::add_extender (Grob * extender)
{
- if (notehead_l_ && melisma_b_) {
- dynamic_cast<Spanner*> (extender)->set_bound (RIGHT, notehead_l_);
- // should the extender finish at the right of the last note of the melisma, or the left?
- // Comments in lyric-extender.hh say left, but right looks better to me. GP.
-
- // Left:
-// extender->set_grob_property ("right-trim-amount", gh_double2scm (0.0));
-
- // Right:
- Real ss = 1.0;
- extender->set_grob_property ("right-trim-amount",
- gh_double2scm (-notehead_l_->extent (notehead_l_, X_AXIS).length ()/ss));
- }
+ if (notehead_ && melisma_b_)
+ {
+ dynamic_cast<Spanner*> (extender)->set_bound (RIGHT, notehead_);
+ // should the extender finish at the right of the last note of the melisma, or the left?
+ // Comments in lyric-extender.hh say left, but right looks better to me. GP.
+
+ // Left:
+ // extender->set_grob_property ("right-trim-amount", gh_double2scm (0.0));
+
+ // Right:
+ Real ss = 1.0;
+ extender->set_grob_property ("right-trim-amount",
+ gh_double2scm (-notehead_->extent (notehead_, X_AXIS).length ()/ss));
+ }
}
bool
-Syllable_group::set_lyric_align (const char *punc, Grob *default_notehead_l)
+Syllable_group::set_lyric_align (const char *punc, Grob *default_notehead)
{
- if (lyric_list_.size ()==0) {
- // No lyrics: nothing to do.
- return true;
- }
-
+ if (lyrics_.size () <= 0)
+ {
+ // No lyrics: nothing to do.
+ return true;
+ }
+
Grob * lyric;
- alignment_i_ = appropriate_alignment (punc);
+ alignment_ = appropriate_alignment (punc);
- // 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_) {
- notehead_l_ = default_notehead_l;
- }
+ /* If there was no notehead in the matching voice context, use the
+ first notehead caught from any voice context (any port in a storm).
+
+
+ Is this wise? Can't the lyric simply be set on a the paper-column,
+ and be done with it. That's just as correct, and won't give strange
+ results if the port-in-the-storms happesn to be involved in a
+ note-collision? --hwn.
+ */
+ if (!notehead_)
+ {
+ notehead_ = default_notehead;
+ }
- group_translation_f_ = amount_to_translate ();
+ group_translation_ = amount_to_translate ();
// set the x alignment of each lyric
- for (int l = 0; l < lyric_list_.size (); l++) {
- lyric = lyric_list_[l];
- lyric->set_grob_property ("self-alignment-X", gh_int2scm (alignment_i_));
- // centre on notehead ... if we have one.
- if (notehead_l_) {
- lyric->set_parent (notehead_l_, X_AXIS);
- lyric->add_offset_callback (Side_position_interface::centered_on_parent_proc, X_AXIS);
- // reference is on the right of the notehead; move it left half way, and add translation
- lyric->translate_axis (group_translation_f_- (notehead_l_->extent (notehead_l_, X_AXIS)).center (), X_AXIS);
+ for (int l = 0; l < lyrics_.size (); l++)
+ {
+ lyric = lyrics_[l];
+ lyric->set_grob_property ("self-alignment-X", gh_int2scm (alignment_));
+ if (notehead_)
+ {
+ /*
+ Centering on parent is done by default (see
+ grob-description.scm); we only have to set the parent.
+ */
+ lyric->set_parent (notehead_, X_AXIS);
+ lyric->translate_axis (group_translation_, X_AXIS);
+ }
}
- }
- return (notehead_l_);
+ return (notehead_);
}
/** determine the distance to translate lyrics to get correct alignment
Rules: If alignment is centre, translate = 0
- Otherwise,
- If (length of longest lyric) < property("end-alignment") * (length of shortest lyric),
- - centre longest lyric on notehead
- Otherwise
- - move so shortest lyric just reaches notehead centre
+ Otherwise,
+ If (length of longest lyric) < (property {begin,end}-alignment) * (length of shortest lyric),
+ - centre longest lyric on notehead
+ Otherwise
+ - move so shortest lyric just reaches notehead centre
*/
Real
Syllable_group::amount_to_translate ()
{
Real translate = 0.0;
- if (alignment_i_ != CENTER) {
- // FIXME: do we really know the lyric extent here? Some font sizing comes later?
- Real l1 = longest_lyric_l_->extent (longest_lyric_l_, X_AXIS).length () / gh_scm2double (longest_lyric_l_->get_grob_property("end-alignment"));
- Real l2 = shortest_lyric_l_->extent (shortest_lyric_l_, X_AXIS).length ();
-
- translate = l1 <? l2;
- translate *= alignment_i_ ;
- }
+ if (alignment_ != CENTER)
+ {
+ switch (alignment_)
+ {
+ // FIXME: do we really know the lyric extent here? Some font sizing comes later?
+ case LEFT:
+ translate = longest_lyric_->extent (longest_lyric_, X_AXIS).length () / gh_scm2double (longest_lyric_->get_grob_property("begin-alignment"));
+ break;
+ case RIGHT:
+ translate = longest_lyric_->extent (longest_lyric_, X_AXIS).length () / gh_scm2double (longest_lyric_->get_grob_property("end-alignment"));
+ break;
+ }
+ if (!gh_scm2bool(longest_lyric_->get_grob_property("ignore-length-mismatch")))
+ {
+ Real l = shortest_lyric_->extent (shortest_lyric_, X_AXIS).length ();
+ translate = l <? translate;
+ }
+
+ translate *= alignment_ ;
+ }
return translate;
}
/** determine what alignment we want.
Rules: if property alignment is set it specifies the alignment
- if first_in_phrase_b_ is set, then alignment is LEFT.
- otherwise if each syllable ends in punctuation, then alignment is RIGHT
- otherwise alignment is centre.
+ if first_in_phrase_b_ is set, then alignment is LEFT.
+ otherwise if each syllable ends in punctuation, then alignment is RIGHT
+ otherwise alignment is centre.
*/
int
Syllable_group::appropriate_alignment (const char *punc)
{
-
- SCM s=this->longest_lyric_l_->get_grob_property ("alignment");
- if (s!=SCM_EOL) {
+ SCM s=this->longest_lyric_->get_grob_property ("alignment");
+ if (s!=SCM_EOL)
+ {
return gh_scm2int (s);
}
Grob * lyric;
bool end_phrase = true;
- for (int l = 0; l < lyric_list_.size () && end_phrase; l++) {
- lyric = lyric_list_[l];
- SCM lyric_scm = lyric->get_grob_property ("text");
- String lyric_str = gh_string_p (lyric_scm)?ly_scm2string (lyric_scm):"";
- char lastchar;
- if (lyric_str.length_i ()>0) {
- lastchar = lyric_str[lyric_str.length_i ()-1];
- /* If it doesn't end in punctuation then it ain't an end of phrase */
- if (! strchr (punc, lastchar)) {
- /*
- FIXME: Document this.
+ for (int l = 0; l < lyrics_.size () && end_phrase; l++)
+ {
+ lyric = lyrics_[l];
+ SCM lyric_scm = lyric->get_grob_property ("text");
+ String lyric_string = gh_string_p (lyric_scm)?ly_scm2string (lyric_scm):"";
+ char lastchar;
+ if (lyric_string.length ()>0)
+ {
+ lastchar = lyric_string[lyric_string.length ()-1];
+ /* If it doesn't end in punctuation then it ain't an end of phrase */
+ if (! strchr (punc, lastchar))
+ {
+ /*
+ FIXME: Document this.
- Special case: trailing space. Here examine the previous character and reverse the
- sense of the test (i.e. trailing space makes a break without punctuation, or
- suppresses a break with punctuation).
- This behaviour can be suppressed by including a space in the
- phrasingPunctuation property, in which case trailing space always means
- the same as punctuation.
-
- FIXME: The extra space throws alignment out a bit.
- */
- if (lastchar == ' ') {
- if (lyric_str.length_i ()>1) {
- lastchar = lyric_str[lyric_str.length_i ()-2];
- if (strchr (punc, lastchar))
- end_phrase=false;
- }
+ Special case: trailing space. Here examine the
+ previous character and reverse the sense of the test
+ (i.e. trailing space makes a break without
+ punctuation, or suppresses a break with punctuation).
+ This behaviour can be suppressed by including a space
+ in the phrasingPunctuation property, in which case
+ trailing space always means the same as punctuation.
+
+ FIXME: The extra space throws alignment out a bit.
+ */
+ if (lastchar == ' ')
+ {
+ if (lyric_string.length ()>1)
+ {
+ lastchar = lyric_string[lyric_string.length ()-2];
+ if (strchr (punc, lastchar))
+ end_phrase=false;
+ }
+ }
+ else
+ end_phrase=false;
+ }
}
- else
- end_phrase=false;
- }
}
- }
if (end_phrase)
return RIGHT;
void
Syllable_group::adjust_melisma_align ()
{
- if (notehead_l_ && lyric_list_.size ()) {
- // override any previous offset adjustments
- Real translation = -group_translation_f_;
- // melisma aligning:
- switch (alignment_i_) {
- // case LEFT: // that's all
- case CENTER: // move right so smallest lyric is left-aligned on notehead
- translation += (shortest_lyric_l_->extent (shortest_lyric_l_, X_AXIS)).length ()/2;
- break;
- case RIGHT: // move right so smallest lyric is left-aligned on notehead
- translation += (shortest_lyric_l_->extent (shortest_lyric_l_, X_AXIS)).length ();
- break;
- }
- group_translation_f_ += translation;
- for (int l = 0; l < lyric_list_.size (); l++) {
- lyric_list_[l]->translate_axis (translation, X_AXIS);
+ if (notehead_ && lyrics_.size ())
+ {
+ // override any previous offset adjustments
+ Real translation = -group_translation_;
+ // melisma aligning:
+ switch (alignment_)
+ {
+ // case LEFT: // that's all
+ case CENTER: // move right so smallest lyric is left-aligned on notehead
+ translation += (shortest_lyric_->extent (shortest_lyric_, X_AXIS)).length ()/2;
+ break;
+ case RIGHT: // move right so smallest lyric is left-aligned on notehead
+ translation += (shortest_lyric_->extent (shortest_lyric_, X_AXIS)).length ();
+ break;
+ }
+ group_translation_ += translation;
+ for (int l = 0; l < lyrics_.size (); l++)
+ {
+ lyrics_[l]->translate_axis (translation, X_AXIS);
+ }
}
- }
}
bool
Syllable_group::is_empty ()
{
- return lyric_list_.size ()==0;
+ return lyrics_.size ()==0;
}
void
Syllable_group::next_lyric ()
{
- first_in_phrase_b_ = (alignment_i_ == RIGHT);
+ first_in_phrase_b_ = (alignment_ == RIGHT);
clear ();
}
Syllable_group *vi = new Syllable_group;
return vi->smobbed_self ();
}
+
+struct Lyric_syllable
+{
+ static bool has_interface (Grob*);
+};
+ADD_INTERFACE (Lyric_syllable,"lyric-syllable-interface",
+ "a single piece of lyrics",
+ "word-space alignment ignore-length-mismatch begin-alignment end-alignment");
+