[EMAIL PROTECTED] writes:
> could anyone please explain to a dummy e.g. how to
> use lilypond's dependencies (which functions to call - when to use
> add_dependency() and for what reason ... etc.).
>
> I'd definitely like to hack on the source, and there's still so much
> missing, but right now it's just a waste of time and it seems virtually
> impossible without comments and documentation. :-((
>
> thank you ..
>
> --
Ah! You have really been looking :-)
The idea of dependencies is the following: the properties of some
graphical objects depend on properties of other types of objects, for
example the placement of a staccato dot depends on the direction of
the stem. This means that the stem-direction has to be calculated
before the staccato dot placement.
You can tell this from the code. (Staff_side captures the placing info
of a staccato dot. )
staff-side.cc
void
Staff_side::add_support (Score_elem*i)
{
support_l_arr_.push (i);
add_dependency (i);
}
Some properties influence horizontal dimensions, so they have to be
calculated before breaking the lines. Some properties depend on the
line breaks chosen. So the calculation of properties like
stem-direction is grouped. For these categories different subtypes of
Score_elem have different virtual functions called do_XXX_processing.
All the passes are listed in lily/super-elem.cc
/**
for administration of what was done already
*/
enum Score_elem_status {
ORPHAN=0, // not yet added to pstaff
VIRGIN, // added to pstaff
PREBROKEN,
PRECALCING,
PRECALCED, // calcs before spacing done
SPACING,
SPACED,
BROKEN,
POSTCALCING, // busy calculating. This is used to trap cyclic deps.
POSTCALCED, // after spacing calcs done
BREWING,
BREWED,
UNLINKING,
UNLINKED,
};
Score_elem has the following virtuals that can be overriden
///executed directly after the item is added to the Paper_score
virtual void do_add_processing();
/// do calculations before determining horizontal spacing
virtual void do_pre_processing();
/// generate rods & springs
virtual void do_space_processing ();
virtual void do_breakable_col_processing();
/// do calculations after determining horizontal spacing
virtual void do_post_processing();
In essence the staccato dot could also have been written as
Staccato_dot::xxx ()
{
Direction d = this->stem_pointer->get_direction ();
/*
currently code would look like
Direction d = this->stem_pointer->direction;
*/
}
and use method calls instead. The reason that this can't be done is
linebreaking: when the score is broken in to lines, a lot of pointers
get changed: if a slur is broken in two pieces, then pointers to the
slur should be changed into pointers to the broken pieces. For this
kind of trickery, you have do_substitute_dependency. It is a derived
call that should make sure that the pointers inside the definition of
(in this example) Staccato_dot are changed:
void
Staff_side::do_substitute_dependency (Score_elem*o, Score_elem*n)
{
support_l_arr_.unordered_substitute (o,n);
}
or (more pseudo codish)
Staccato_dot::do_substitute_dependency (Score_elem* old_pointer, Score_elem*
new_pointer)
{
if (this->stem_pointer == old_pointer)
{
this->stem_pointer = (Stem*) new_pointer;
}
}
The real work for the dependencies is done in score-elem.cc:
void
Score_elem::calcalute_dependencies (int final, int busy,
Score_elem_method_pointer funcptr)
{
if (status_i_ >= final)
return;
assert (status_i_!= busy);
status_i_= busy;
for (int i=0; i < dependency_size(); i++)
dependency (i)->calcalute_dependencies (final, busy, funcptr);
Link_array<Score_elem> extra (get_extra_dependencies());
for (int i=0; i < extra.size(); i++)
extra[i]->calcalute_dependencies (final, busy, funcptr);
invalidate_cache (X_AXIS);
invalidate_cache (Y_AXIS);
(this->*funcptr)(); /* this is the call to do_XXX_processing*/
status_i_= final;
}
The order for different passes comes from p-score.cc
void
Paper_score::process ()
{
clean_cols ();
print ();
*mlog << _ ("Preprocessing elements...") << " " << flush;
super_elem_l_->breakable_col_processing ();
super_elem_l_->pre_processing ();
*mlog << '\n' << _ ("Calculating column positions...") << " " << flush;
super_elem_l_->space_processing ();
calc_breaking ();
*mlog << _ ("Postprocessing elements...") << " " << endl;
super_elem_l_->post_processing ();
tex_output ();
}
Does this satisfy your curiosity? I will be writing a paper on this
system RSN, but I'd be glad to explain more. It helps me with writing
my paper :-)
--
Han-Wen Nienhuys, [EMAIL PROTECTED] ** GNU LilyPond - The Music Typesetter
http://www.cs.uu.nl/people/hanwen/lilypond/index.html