+2002-08-03 Han-Wen <hanwen@cs.uu.nl>
+
+ * lily/beam.cc (consider_auto_knees): rewrite function; now only
+ consider horizontal knees. Fixes input/bugs/bizzarre-beam.ly
+
+ * lily/syllable-group.cc (set_lyric_align): fix centering on note
+ head for `normal' lyrics. This fixes input/bugs/lyrics-spacing.ly.
+
2002-08-02 Han-Wen <hanwen@cs.uu.nl>
* lily/beam.cc (connect_beams): fix quarter note beams.
\property LyricsVoice . stanza = "Ernie"
@end example
+The convention for naming @code{LyricsVoice} and @code{Voice} must
+also be used to get melismata on rests correct.
+
+
@node More movements
@section More movements
endif
+final-install:
+ @echo
+ @echo " *** Before running, buildscripts/out/lilypond-{profile,login}"
+ @echo " *** must be run. You're advised to source these scripts from your "
+ @echo " *** login scripts. For more information, see Invoking LilyPond in the manual."
+ @echo
+
TOP_HTMLS = index.html examples.html
examples: web-reqs
+++ /dev/null
-
-
-\score{ \notes {g''4 [<e'''8 g> g'']
-\notes\relative c'{
-
- \times 2/3{[d16 fis' d,]} \times 2/3{[cis g'' cis,,]}
- a'16 cis a, g''' % Used to give a nice beam directed upwards.
- <{\stemUp a,,4:32} \context Voice=lower{\stemDown d,:32}>
-
-}
- }}
+++ /dev/null
-%
-% space after barline on 1st staff due to time sig.
-%
-
-\score{
- \notes\relative c'\context GrandStaff{
-
-c4 d e f |
-g a b c | \break
-
-<{
-d c b a |
- g f e d}
- \context Staff=lower{
-% \property Staff.TimeSignature = \turnOff
-
-b' a g f |
- e d c b |}> \break
-
-c1
-}
-\paper{
- \translator{
- \GrandStaffContext
- \consists "Instrument_name_engraver"
- }
-}
-}
+++ /dev/null
-\header {
-
-texidoc=" Funky kneed beams with beamlets also work. The beamlets
-should be pointing to the note head.
-"
-
-}
-
-\score {
- \notes\relative c' {
- c16 c''8 c,,16
- c16 c''8 c16
- c16 c,,8 c16
-
- }
- \paper { linewidth = -1 }
-}
-
+++ /dev/null
-\version "1.5.68"
-
-%
-%
-
-\header{
-texidoc = "
-Adding a @code{Bar_engraver} to the LyricsVoice context makes sure that
-lyrics don't collide with barlines.
-
-Lyrics with barline colliding is fine now, BUT
-There's an horizontal gap between staff and end bar .
-"
-}
-
-\score {
- \context StaffGroup <
- \notes \context Staff {
- b1 \bar "|:" b1 \bar ":|"
- }
- \lyrics\context Lyrics <
- \context LyricsVoiceWithBars {
-% thisContextHasBarEngraver1 added
- ThisContextCertainlyHasBarEngraverAddedButThereHasBeenSomethingFunnyBefore1. Here.
- }
- \context LyricsVoice {
- this4 one has no BarEngraverAddedToContext1
- }
- >
- \notes \context Staff = SB { b1 b1 }
- >
- \paper {
- linewidth = -1.0\cm
- \translator {
- \LyricsContext
- \accepts "LyricsVoiceWithBars"
- }
- \translator {
- \LyricsVoiceContext
- \consists "Bar_engraver"
- \name "LyricsVoiceWithBars"
- }
- \translator {
- \LyricsVoiceContext
- }
- }
-}
+++ /dev/null
-\include "norsk.ly"
-
-\header {
-texidoc ="``baz'' should be centered on the a (tenor voice), but it is
-not."
-}
-
-\version "1.5.68"
-
-sop = \notes \transpose c'' {e2 e fis1 }
-alt = \notes \relative c' {cis2 e e d }
-ten = \notes \relative c' {a2 a a1 }
-txt = \lyrics {foo2 bar baz jazz }
-
-\score {
- <
- \context Staff = up \notes <
- \context Voice=sopv {\stemUp \sop}
- \context Voice=altv {\stemDown \alt}
- >
- \context Staff = down \notes < \clef "F"
- \context Voice=tenv {\stemUp \ten}
- >
- \context Lyrics = la { \txt }
- >
- \paper { linewidth = -1 }
-}
+++ /dev/null
-\version "1.5.68"
-\header {
-
-texidoc="
-The definition of markup is incomplete.
-
-Ideally, either the input is valid, and all information therein is
-used, or it is invalid, and an error message is produced."
-
-}
-
-
-\score { \notes \relative c' {
- f_#'(lines "one" ( "tow"))
-
- % FIXED:three ignored
- f_#'(lines "one" ( "two" "three" ))
-
- % right way of using multiple markups
- f_#'(lines "one" ((bold italic) "towo"))
-
- % italic ignored.
- % possibly explicit relaxed code for chords stuff, must check
- f_#'(lines "one" (bold italic "towo"))
-
- }}
\addlyrics
\notes {
\property Staff.automaticMelismata= ##t
- c4 () c r c
+ \context Voice = melismaBla { c4 () c r c }
}
- \context Lyrics \lyrics { foo __ bar }
+ \context LyricsVoice = "melismaBla-1" \lyrics { foo __ bar }
\context Staff=foolMelismata \notes{
- c4 ( c c ) c
+ c4 c c c
}
- \context Staff=foolMelismata \notes{
+ \context Staff=OtherFoolMelismata \notes{
c1
}
>
-}
\ No newline at end of file
+}
+++ /dev/null
-\version "1.5.68"
-
-\header{
-texidoc = "
-Slurs should be attached to note heads, except when they would collide
-with beams. Also see: ophee-slurs.
-"
-}
-\score{
- \notes \relative c''{
- \property Voice.Slur \set #'direction = #1
- a8( a )a4
- a4( a8 )a
- a8 a()a4
- a4() a8 a
- }
- \paper{
- indent = 0.0
- linewidth = 100.\mm
- }
-}
+++ /dev/null
-\version "1.5.68"
-
-\header{
-texidoc = "
- Wouldbe-steep-starting slurs look ugly.
-" }
-
-\score {
- \notes \relative c'' {
- \property Voice.Stem \set #'direction = #1
- \property Voice.Slur \set #'direction = #1
- d,32( d'4 )d8..
- \property Voice.Slur \set #'attachment = #'(stem . stem)
- d,32( d'4 )d8..
- }
- \paper {
- linewidth = -1.
- }
-}
+++ /dev/null
-
-% ??
-
-\version "1.5.68"
-
-\score{
- \notes\relative c''{
- \time 2/4
- [f8 e d f, (] | \break
- [) a'8. gis16 fis8. cis16] |
- }
- \paper{
- linewidth = 3.5\cm
- indent = .0
- }
-}
-
\version "1.5.68"
-\header{
-texidoc="One automatic knee"
+\header{ texidoc="Automatic kneeing. A knee is made when a horizontal
+beam fits in a gap between note heads that is larger than a predefined
+threshold.
+"
}
\score {
\context Staff \notes\relative c''{
[c'8 c,,] [c8 e']
+ [c,16 e g c e g c c,,]
}
\paper{
linewidth = 40*\staffspace
-% Now by default
-% \translator {
-% \VoiceContext
-% Beam \override #'auto-knee-gap = #7
-% }
}
}
}
}
-/* Simplistic auto-knees; only consider vertical gap between two
- adjacent chords.
+/*
+ A union of intervals in the real line.
+
+ Abysmal performance (quadratic) for large N, hopefully we don't have
+ that large N. In any case, this should probably be rewritten to use
+ a balanced tree.
+ */
+struct Int_set
+{
+ Array<Interval> allowed_regions_;
- This may decide for a knee that's impossible to fit sane scoring
- criteria (eg, stem lengths). We may need something smarter. */
+ Int_set()
+ {
+ set_full();
+ }
+
+ void set_full()
+ {
+ allowed_regions_.clear();
+ Interval s;
+ s.set_full ();
+ allowed_regions_.push (s);
+ }
+
+ void remove_interval (Interval rm)
+ {
+ for (int i = 0; i < allowed_regions_.size(); )
+ {
+ Interval s = rm;
+
+ s.intersect (allowed_regions_[i]);
+
+ if (!s.empty_b ())
+ {
+ Interval before = allowed_regions_[i];
+ Interval after = allowed_regions_[i];
+
+ before[RIGHT] = s[LEFT];
+ after[LEFT] = s[RIGHT];
+
+ if (!before.empty_b())
+ {
+ allowed_regions_.insert (before, i);
+ i++;
+ }
+ allowed_regions_.del (i);
+ if (!after.empty_b ())
+ {
+ allowed_regions_.insert (after, i);
+ i++;
+ }
+ }
+ else
+ i++;
+ }
+ }
+};
+
+
+/*
+ Only try horizontal beams for knees. No reliable detection of
+ anything else is possible here, since we don't know funky-beaming
+ settings, or X-distances (slopes!) People that want sloped
+ knee-beams, should set the directions manually.
+ */
void
-Beam::consider_auto_knees (Grob *me, Direction d)
+Beam::consider_auto_knees (Grob* me, Direction d)
{
SCM scm = me->get_grob_property ("auto-knee-gap");
-
if (!gh_number_p (scm))
- return;
+ return ;
+
+ Real threshold = gh_scm2double (scm);
- bool knee_b = false;
+ Int_set gaps;
+
+ gaps.set_full ();
- Real staff_space = Staff_symbol_referencer::staff_space (me);
- Real gap = gh_scm2double (scm) / staff_space;
Link_array<Grob> stems=
Pointer_group_interface__extract_grobs (me, (Grob*)0, "stems");
Grob *common = common_refpoint_of_array (stems, me, Y_AXIS);
-
- int l = 0;
- for (int r=1; r < stems.size (); r++)
+ Real staff_space = Staff_symbol_referencer::staff_space (me);
+
+ Array<Interval> hps_array;
+ for (int i=0; i < stems.size (); i++)
{
- if (!Stem::invisible_b (stems[r-1]))
- l = r - 1;
- Grob *right = stems[r];
- Grob *left = stems[l];
- if (Stem::invisible_b (left))
+ Grob* stem = stems[i];
+ if (Stem::invisible_b (stem))
continue;
- if (Stem::invisible_b (right))
- continue;
-
- Real left_y = Stem::extremal_heads (left)[d]
- ->relative_coordinate (common, Y_AXIS);
- Real right_y = Stem::extremal_heads (right)[-d]
- ->relative_coordinate (common, Y_AXIS);
+
- Real dy = right_y - left_y;
+ Interval hps = Stem::head_positions (stem);
- if (abs (dy) >= gap)
+ if(!hps.empty_b())
{
- knee_b = true;
- Direction knee_dir = (right_y > left_y ? UP : DOWN);
- if (!Stem::invisible_b (left)
- && left->get_grob_property ("dir-forced") != SCM_BOOL_T)
- {
- Directional_element_interface::set (left, knee_dir);
- left->set_grob_property ("dir-forced", SCM_BOOL_T);
-
- }
- if (!Stem::invisible_b (right)
- && stems[r]->get_grob_property ("dir-forced") != SCM_BOOL_T)
+ hps[LEFT] += -1;
+ hps[RIGHT] += 1;
+ hps *= staff_space * 0.5 ;
+ hps += stem->relative_coordinate (common, Y_AXIS);
+
+ if (to_boolean (stem->get_grob_property ("dir-forced")))
{
- Directional_element_interface::set (right, -knee_dir);
- right->set_grob_property ("dir-forced", SCM_BOOL_T);
+ Direction stemdir =Directional_element_interface::get (stem);
+ hps[-stemdir] = - stemdir * infinity_f;
}
}
+ hps_array.push (hps);
+
+ gaps.remove_interval (hps);
}
- if (knee_b)
+ Interval max_gap;
+ Real max_gap_len =0.0;
+
+ for (int i = gaps.allowed_regions_.size() -1; i >= 0 ; i--)
{
- me->set_grob_property ("knee", SCM_BOOL_T);
-
- for (int i=0; i < stems.size (); i++)
- stems[i]->set_grob_property ("stem-info", SCM_EOL);
+ Interval gap = gaps.allowed_regions_[i];
+
+ /*
+ the outer gaps are not knees.
+ */
+ if (isinf (gap[LEFT]) || isinf(gap[RIGHT]))
+ continue;
+
+ if (gap.length () >= max_gap_len)
+ {
+ max_gap_len = gap.length();
+ max_gap = gap;
+ }
+ }
+
+ if (max_gap_len > threshold)
+ {
+ int j = 0;
+ for (int i = 0; i < stems.size(); i++)
+ {
+ Grob* stem = stems[i];
+ if (Stem::invisible_b (stem))
+ continue;
+
+ Interval hps = hps_array[j++];
+
+
+ Direction d = (hps.center () < max_gap.center()) ?
+ UP : DOWN ;
+
+ stem->set_grob_property ("direction", gh_int2scm (d));
+
+ /*
+ UGH. Check why we still need dir-forced; I think we can
+ junk it.
+ */
+ stem->set_grob_property ("dir-forced", SCM_BOOL_T);
+
+ hps.intersect (max_gap);
+ assert (hps.empty_b () || hps.length () < 1e-6 );
+ }
}
}
+
+
/* Set stem's shorten property if unset.
TODO:
{
bool first_in_phrase_b_;
Grob * notehead_;
- Link_array<Grob> lyric_list_;
+ Link_array<Grob> lyrics_;
Grob * longest_lyric_;
Grob * shortest_lyric_;
int alignment_;
void add_extender (Grob * extender);
void set_melisma () { melisma_b_ = true; }
bool get_melisma () { return melisma_b_; }
- int lyric_count () { return lyric_list_.size (); }
+ int lyric_count () { return lyrics_.size (); }
void clear ();
bool is_empty ();
bool set_lyric_align (const char *punc, Grob *default_notehead);
/* match found */
// (key . ((alist_entry . old_entry) . previous_entry))
if (to_boolean (ly_cdadr (s)))
- { // it's an old entry ... make it a new one
+ {
+ // it's an old entry ... make it a new one
SCM val = gh_cons (gh_cons (ly_caadr (s), SCM_BOOL_F), ly_cddr (s));
voice_alist_ = scm_assoc_set_x (voice_alist_, ly_car (s), val);
return unsmob_voice_entry (ly_caar (val));
}
- else { // the entry is current ... return it.
+ else
+ {
+ // the entry is current ... return it.
SCM entry_scm = ly_caadr (s);
return unsmob_voice_entry (entry_scm);
}
Syllable_group * v = lookup_context_id (context_id);
v->set_melisma ();
}
-
+
+/*
+ TODO: this engraver is always on, also for orchestral scores. That
+ is a waste of time and space. This should be switched on
+ automatically at the first Lyrics found.
+ */
void
Lyric_phrasing_engraver::acknowledge_grob (Grob_info i)
{
{
voice_context_id = ly_scm2string (voice_context_scm);
}
- else {
- voice_context_id = get_context_id (i.origin_trans_->daddy_trans_, "LyricsVoice");
- voice_context_id = trim_suffix (voice_context_id);
- }
+ else
+ {
+ voice_context_id = get_context_id (i.origin_trans_->daddy_trans_, "LyricsVoice");
+ voice_context_id = trim_suffix (voice_context_id);
+ }
record_lyric (voice_context_id, h);
return;
}
SCM v_entry = ly_cdar (v);
// ((current . oldflag) . previous)
if (!to_boolean (ly_cdar (v_entry)))
- { // not an old entry left over from a prior note ...
+ {
+ // not an old entry left over from a prior note ...
Syllable_group *entry = unsmob_voice_entry (ly_caar (v_entry));
/*
ENTER_DESCRIPTION(Lyric_phrasing_engraver,
- /* descr */ "",
+ /* descr */ "
+This engraver combines note heads and lyrics for alignment.
+
+This engraver is switched on by default. Turn it off for faster
+processing of orchestral scores.
+",
/* creats*/ "",
/* acks */ "lyric-syllable-interface note-head-interface lyric-extender-interface",
/* reads */ "automaticPhrasing melismaEngraverBusy associatedVoice phrasingPunctuation",
#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 ()
Syllable_group::clear ()
{
notehead_=0;
- lyric_list_.clear ();
+ lyrics_.clear ();
longest_lyric_=0;
shortest_lyric_=0;
melisma_b_ = false;
Syllable_group::copy (Syllable_group *from)
{
notehead_ = from->notehead_;
- lyric_list_ = from->lyric_list_;
+ lyrics_ = from->lyrics_;
longest_lyric_ = from->longest_lyric_;
shortest_lyric_ = from->shortest_lyric_;
melisma_b_ = from->melisma_b_;
void
Syllable_group::set_notehead (Grob * notehead)
{
- if (!notehead_) {
- /* there should only be a single notehead, so silently ignore any extras */
- notehead_=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_) {
- 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;
- }
+ 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_ = shortest_lyric_ = lyric;
}
void
Syllable_group::add_extender (Grob * extender)
{
- 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));
- }
+ 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)
{
- if (lyric_list_.size ()<=1) {
- // No lyrics or single line: nothing to do.
- return true;
- }
+ if (lyrics_.size ()<=1)
+ {
+ // No lyrics or single line: nothing to do.
+ return true;
+ }
Grob * lyric;
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_) {
- notehead_ = default_notehead;
- }
+ /* 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_ = 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_));
- // centre on notehead ... if we have one.
- if (notehead_) {
- lyric->set_parent (notehead_, X_AXIS);
- lyric->add_offset_callback (Self_alignment_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_- (notehead_->extent (notehead_, 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_);
}
/** determine the distance to translate lyrics to get correct alignment
Rules: If alignment is centre, translate = 0
- 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
+ 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_ != 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;
- }
+ 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_ ;
- }
+ 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_->get_grob_property ("alignment");
- if (s!=SCM_EOL) {
+ 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_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.
+ 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_string.length ()>1) {
- lastchar = lyric_string[lyric_string.length ()-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_ && lyric_list_.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 < 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
struct Lyric_syllable
{
- static bool has_interface (Grob*);
+ 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");
+ "a single piece of lyrics",
+ "word-space alignment ignore-length-mismatch begin-alignment end-alignment");
(define (boolean-or-symbol? x)
(or (boolean? x) (symbol? x)))
-(define (number-or-boolean? x)
- (or (number? x) (boolean? x)))
-
(define (number-or-string? x)
(or (number? x) (string? x)))
(,procedure? . "procedure")
(,boolean-or-symbol? . "boolean or symbol")
(,number-or-string? . "number or string")
- (,number-or-boolean? . "number or boolean")
(,markup? . "markup (list or string)")
(,number-or-grob? . "number or grob")
))
(slope-limit . 0.2)
(flag-width-function . ,default-beam-flag-width-function)
(damping . 1)
- (auto-knee-gap . 7)
+ (auto-knee-gap . 5.5)
(font-name . "cmr10")
(space-function . ,Beam::space_function)
(meta . ((interfaces . (staff-symbol-referencer-interface beam-interface spanner-interface))))
(LyricText
. (
(molecule-callback . ,Text_item::brew_molecule)
- (X-offset-callbacks . (,Self_alignment_interface::aligned_on_self))
+ (X-offset-callbacks . (,Self_alignment_interface::centered_on_parent
+ ,Self_alignment_interface::aligned_on_self))
(self-alignment-X . 0)
(word-space . 0.6)
(ignore-length-mismatch . #f)
(end-alignment . 2)
(font-family . roman)
(font-shape . upright)
+
;; duh, side-position-interface?
(meta . ((interfaces . (lyric-syllable-interface self-alignment-interface text-interface font-interface item-interface ))))
))
attachments to prevent ugly slurs. [fixme: we need more documentation here].
.")
(grob-property-description 'auto-properties boolean? "if true, as many properties of this grob as possible will be determined automatically from the musical context.")
-(grob-property-description 'auto-knee-gap number-or-boolean? "the minimal smallest gap between two adjacent beamed chords for which beam will create auto-knees. Set to false for no auto knees." )
+(grob-property-description 'auto-knee-gap number? "If a gap is found between noteheads
+where a horizontal beam fits that is larger than this number, make a kneed beam.")
(grob-property-description 'axes list? "list of axis numbers.
In the case of alignment grobs, this should contain only one number.")
(grob-property-description 'bar-size number? "size of a bar line.")
install-strip:
$(MAKE) INSTALL="$(INSTALL) -s" install
+final-install:
+
install: local-install
$(LOOP)
+ $(MAKE) final-install
local-install: