2004-02-05 Han-Wen Nienhuys <hanwen@xs4all.nl>
+ * lily/axis-group-engraver.cc (acknowledge_grob): also take
+ lyric-interface; this prevents lines with only extender lines from
+ being junked.
+
+ * scm/define-grob-interfaces.scm (lyric-interface): new interface
+
+ * lily/lyric-extender.cc (brew_molecule): get line breaking and
+ extenders right, for once and for all (hopefully).
+
+ * lily/break-substitution.cc (substitute_one_mutable_property):
+ clear old 'all-elements for System grobs.
+
* lily/new-lyric-combine-music-iterator.cc (find_voice): make sure
that associatedVoiceContext is always assigned when music & lyrics
are found.
-\version "2.1.10"
-\header{
- texidoc =
+\version "2.1.19"
+\header
+{
- "Extenders that end a staff should not extend past the staff."
+ texidoc = "Lyric extenders run to the end of the line if it
+continues the next line. Otherwise, it should run to the last note
+of the melisma."
}
-sopran = \notes \relative c'' {
-\time 3/4 a2.( | \break
- g2) g4
-}
-
-text = \lyrics {
-Aaaaa __ aaaaaah
-}
-
\score {
-<<
-
- \context Voice = "foo" \sopran
- \context LyricsVoice \lyricsto foo \text
->>
-\paper { linewidth = 5.0\cm
-}
+ <<
+ \context Voice=A \notes {
+ a1 ( a1 \break
+ a) a2( b) \break
+ a2
+ }
+ \lyricsto A \context LyricsVoice \lyrics { a __ a __ ha }
+ >>
+ \paper {
+ raggedright = ##t
+ }
}
-
Hara_kiri_engraver::acknowledge_grob (Grob_info i)
{
Axis_group_engraver::acknowledge_grob (i);
- if (i.grob_->internal_has_interface (ly_symbol2scm ("rhythmic-grob-interface")))
+ if (i.grob_->internal_has_interface (ly_symbol2scm ("rhythmic-grob-interface"))
+ || i.grob_->internal_has_interface (ly_symbol2scm ("lyric-interface"))
+ )
{
Hara_kiri_group_spanner::add_interesting_item (staffline_, i.grob_);
}
a huge recursion in the GC routine.
*/
- /*
- This was introduced in 1.3.49 as a measure to prevent
- programming errors. It looks rather expensive (?).
-
- TODO:
-
- benchmark , document when (what kind of programming
- errors) this happens.
- */
if (sc->common_refpoint (line, X_AXIS)
&& sc->common_refpoint (line, Y_AXIS))
{
}
#endif
+ /*
+ see below.
+ */
+ if (sym == ly_symbol2scm ("all-elements"))
+ sc->set_grob_property ("all-elements", SCM_EOL);
+
sc->mutable_property_alist_ = scm_acons (sym, newval,
sc->mutable_property_alist_);
}
SCM newval = (type == grob_list_p)
? substitute_grob_list (val)
- : do_break_substitution(val);
+ : do_break_substitution (val);
+ /*
+ For the substitution of a single property, we tack the result onto
+ mutable_property_alist_ ; mutable_property_alist_ is empty after
+ Grob::Grob (Grob const&), except that System has all-elements set,
+ as a side product of typeset_grob() on newly copied spanners.
+
+ Here we clear that list explicitly to free some memory and
+ counter some of the confusion I encountered while debugging
+ another problem
+
+ (hwn 4/2/04)
+ */
+ if (sym == ly_symbol2scm ("all-elements"))
+ sc->set_grob_property ("all-elements", SCM_EOL);
+
sc->mutable_property_alist_ = scm_cons (scm_cons (sym, newval),
sc->mutable_property_alist_);
}
{
Spanner *orig = dynamic_cast<Spanner*> (spanner->original_);
- if (spanner->break_index_ < orig->broken_intos_.size()-1)
+ if (spanner->get_break_index () < orig->broken_intos_.size()-1)
{
- Spanner * next = orig->broken_intos_[spanner->break_index_+1];
+ Spanner * next = orig->broken_intos_[spanner->get_break_index () + 1];
SCM cols = next->get_grob_property ("columns");
if (gh_pair_p (cols))
{
if (!type_check_assignment (sym, gh_cdr (s),
ly_symbol2scm ("backend-type?")))
abort ();
+
check_interfaces_for_property (this, sym);
}
void
Grob::substitute_mutable_properties (SCM crit, SCM orig)
{
- set_break_subsititution(crit);
+ set_break_subsititution (crit);
mutable_property_alist_ = substitute_mutable_property_alist (orig);
}
self_scm_ = SCM_EOL;
immutable_property_alist_ = s.immutable_property_alist_;
-
mutable_property_alist_ = SCM_EOL;
/*
}
-
-
-
MAKE_SCHEME_CALLBACK (Grob,molecule_extent,2);
SCM
Grob::molecule_extent (SCM element_smob, SCM scm_axis)
if (sp)
{
+ /*
+ This is the original spanner. We use a special function
+ because some Spanners have enormously long lists in their
+ properties.
+ */
for (SCM s = mutable_property_alist_; gh_pair_p(s);
s = gh_cdr(s))
{
sp->substitute_one_mutable_property (gh_caar (s),
gh_cdar (s));
-
}
}
class Lyric_extender
{
public:
+ static bool is_visible (Grob*);
static bool has_interface (Grob*);
DECLARE_SCHEME_CALLBACK (brew_molecule, (SCM ));
};
*/
class Spanner : public Grob {
Drul_array<Item*> spanned_drul_;
+ int break_index_;
public:
DECLARE_SCHEME_CALLBACK (set_spacing_rods, (SCM));
Link_array<Spanner> broken_intos_;
- int break_index_;
+ int get_break_index () const;
// todo: move to somewhere else.
Real get_broken_left_end_align () const;
void substitute_one_mutable_property (SCM sym, SCM val) ;
#include "note-head.hh"
#include "group-interface.hh"
+
+bool
+Lyric_extender::is_visible (Grob *gr)
+{
+ Spanner*me = dynamic_cast<Spanner*> (gr);
+
+ SCM heads = me->get_grob_property ("heads");
+ int l = scm_ilength (heads);
+ if (l == 0)
+ return false;
+
+ return true;
+}
+
MAKE_SCHEME_CALLBACK (Lyric_extender,brew_molecule,1)
SCM
Lyric_extender::brew_molecule (SCM smob)
Real right_point
= left_point + (robust_scm2double (minlen,0));
- if (r->break_status_dir ())
- right_point = infinity_f;
- else
+ Spanner *orig = dynamic_cast<Spanner*> (me->original_);
+ bool last_line = orig
+ && (me->get_break_index () == orig->broken_intos_.size() - 2)
+ && !Lyric_extender::is_visible (orig->broken_intos_.top ());
+
+
+ if (heads.size ())
right_point = right_point >? heads.top ()->extent (common, X_AXIS)[RIGHT];
-
+
Real h = sl * robust_scm2double (me->get_grob_property ("thickness"), 0);
Real pad = 2* h;
- right_point = right_point <? (r->extent (common, X_AXIS)[LEFT] - pad);
- if (isinf (right_point))
- return SCM_EOL;
+ if (!r->break_status_dir ())
+ right_point = right_point <? (r->extent (common, X_AXIS)[LEFT] - pad);
+ else if (!last_line)
+ {
+ /*
+ run to end of line.
+ */
+ right_point = right_point >? (r->extent (common, X_AXIS)[LEFT] - pad);
+ }
+ if (isinf (right_point))
+ {
+ programming_error ("Right point of extender not defined?");
+ right_point = r->relative_coordinate (common, X_AXIS);
+ }
left_point += pad;
broken_intos_[i]->break_index_ = i;
}
+int
+Spanner::get_break_index ()const
+{
+ return break_index_;
+}
+
void
Spanner::set_my_columns ()
{
break_index_ = 0;
spanned_drul_[LEFT]=0;
spanned_drul_[RIGHT]=0;
+
Group_interface::add_thing (this, ly_symbol2scm ("interfaces"), ly_symbol2scm ("spanner-interface"));
-
-
}
Spanner::Spanner (Spanner const &s)
programming_error ("Adding element twice.");
elem->pscore_ = pscore_;
- Pointer_group_interface::add_grob (this, ly_symbol2scm ("all-elements"),elem);
+ Pointer_group_interface::add_grob (this, ly_symbol2scm ("all-elements"), elem);
scm_gc_unprotect_object (elem->self_scm ());
}
(bx . ,(ly:make-pitch -1 6 DOUBLE-SHARP))
)
-pitchnames = pitchnamesEnglish
+pitchnames = \pitchnamesEnglish
\version "2.1.19"
"a single piece of lyrics"
'())
+(ly:add-interface
+ 'lyric-interface
+ "Any object that is related to lyrics."
+ '())
+
(ly:add-interface
'mark-interface
"a rehearsal mark"
(minimum-length . 0.5)
(molecule-callback . ,Hyphen_spanner::brew_molecule)
(Y-extent-callback . ,Grob::point_dimension_callback)
- (meta . ((interfaces . (lyric-hyphen-interface spanner-interface))))
+ (meta . ((interfaces . (lyric-interface lyric-hyphen-interface
+ spanner-interface))))
))
(LyricExtender
(thickness . 0.8) ; linethickness
(minimum-length . 1.5)
(Y-extent-callback . ,Grob::point_dimension_callback)
- (meta . ((interfaces . (lyric-extender-interface spanner-interface))))
+ (meta . ((interfaces . (lyric-interface
+ lyric-extender-interface spanner-interface))))
))
(LyricText