+2002-07-03 Han-Wen <hanwen@cs.uu.nl>
+
+ * lily/grob-property.cc (HASHING_FOR_MUTABLE_PROPS): experiment:
+ try hash tables for mutable properties.
+
+ * lily/align-interface.cc: remove aligned-interface and props
+ minimum-space-pair extra-space
+
+ * lily/grob-property.cc: new file move grob prop handling here.
+
+ * lily/lily-guile.cc (ly_deep_copy): add vector support
+
+ * lily/break-substitution.cc (do_break_substitution): add vector
+ support.
+
+ * lily/spanner.cc: remove extend_spanner_over_* funcs.
+
2002-07-02 Jan Nieuwenhuizen <janneke@gnu.org>
* stepmake/aclocal.m4 (STEPMAKE_GET_VERSION): Workaround for
&& Hara_kiri_group_spanner::has_interface (elems[j]))
Hara_kiri_group_spanner::consider_suicide (elems[j]);
- if (!ly_pair_p (elems[j]-> immutable_property_alist_))
+ if (!elems[j]-> live())
elems.del(j);
}
/*
Hairy function to put elements where they should be. Can be tweaked
- from the outside by setting minimum-space-pair and extra-space in its
+ from the outside by setting extra-space in its
children
We assume that the children the refpoints of the children are still
{
Grob *e =dynamic_cast<Grob*> (all_grobs[i]);
- // todo: fucks up if item both in Halign & Valign.
- SCM min_dims = e->remove_grob_property ("minimum-space-pair");
- if (gh_pair_p (min_dims) &&
- gh_number_p (ly_car (min_dims))
- && gh_number_p (ly_cdr (min_dims)))
- {
- y.unite (ly_scm2interval (min_dims));
- }
-
- SCM extra_dims = e->remove_grob_property ("extra-space");
- if (gh_pair_p (extra_dims) &&
- gh_number_p (ly_car (extra_dims))
- && gh_number_p (ly_cdr (extra_dims)))
- {
- y[LEFT] += gh_scm2double (ly_car (extra_dims));
- y[RIGHT] += gh_scm2double (ly_cdr (extra_dims));
- }
-
elems.push (e);
dims.push (y);
}
{
bool has_interface (Grob*);
};
-ADD_INTERFACE (Foobar, "aligned-interface",
- "read by align-interface",
- "minimum-space-pair extra-space");
Special keys for the alist are 'first-note and 'next-note, signifyign
the first note on a line, and the next note halfway a line.
+Rules for this spacing are much more complicated than this.
+See [Wanske] page 126 -- 134, [Ross] pg 143 -- 147
+
+
",
"break-align-symbol break-alignment-done space-alist");
/*
- Do break substitution in S, using CRITERION. Return new value.
- CRITERION is either a SMOB pointer to the desired line, or a number
- representing the break direction. Do not modify SRC.
+ Do break substitution in S, using CRITERION. Return new value.
+ CRITERION is either a SMOB pointer to the desired line, or a number
+ representing the break direction. Do not modify SRC.
- It is rather tightly coded, since it takes a lot of time; it is
- one of the top functions in the profile.
+ It is rather tightly coded, since it takes a lot of time; it is
+ one of the top functions in the profile.
- We don't pass break_criterion as a parameter, since it is
- `constant', but takes up stack space.
-
- It would be nice if we could do this in-place partially. We now
- generate a lot of garbage.
- */
+ We don't pass break_criterion as a parameter, since it is
+ `constant', but takes up stack space.
+ It would be nice if we could do this in-place partially. We now
+ generate a lot of garbage.
+*/
SCM
do_break_substitution (SCM src)
{
{
return substitute_grob (unsmob_grob (src));
}
+ else if (gh_vector_p (src))
+ {
+ int l = SCM_VECTOR_LENGTH (src);
+ SCM nv = scm_c_make_vector (l, SCM_UNDEFINED);
+
+ for (int i =0 ; i< l ; i++)
+ {
+ SCM si = gh_int2scm (i);
+ scm_vector_set_x (nv, si, do_break_substitution (scm_vector_ref (src, si)));
+ }
+ }
else if (ly_pair_p (src))
{
/*
/*
Although the substitution can be written as
- mutable_property_alist_ = do_substitution (mutable_property_alist_),
+ property_alist = do_substitution (other_property_alist),
we have a special function here: we want to invoke a special
function for lists of grobs. These can be very long for large
pthreads. pthreads impose small limits on the stack size.
*/
SCM
-substitute_mutable_properties (SCM alist)
+substitute_mutable_property_alist (SCM alist)
{
if (!grob_list_p)
grob_list_p = scm_c_eval_string ("grob-list?");
return l;
}
+
+
typeset_all ();
if (line_spanner_
- && line_spanner_->immutable_property_alist_ == SCM_EOL)
+ && !line_spanner_->live())
line_spanner_ = 0;
if (line_spanner_)
{
}
if (cresc_p_
- && cresc_p_->immutable_property_alist_ == SCM_EOL)
+ && !cresc_p_->live())
cresc_p_ = 0;
if (cresc_p_)
{
Maybe just check at typeset_grob ()?
*/
if (finished_cresc_p_
- && finished_cresc_p_->immutable_property_alist_ == SCM_EOL)
+ && !finished_cresc_p_->live())
finished_cresc_p_ = 0;
if (finished_line_spanner_
- && finished_line_spanner_->immutable_property_alist_ == SCM_EOL)
+ && !finished_line_spanner_->live())
finished_line_spanner_ = 0;
if (finished_cresc_p_)
/*
We used to have
- extend_spanner_over_elements (finished_line_spanner_);
+ extend-spanner-over-elements (finished_line_spanner_);
but this is rather kludgy, since finished_line_spanner_
typically has a staff-symbol field set , extending it over the
{
if (line_spanner_
/* Don't refill killed spanner */
- && line_spanner_->immutable_property_alist_ != SCM_EOL)
+ && line_spanner_->live())
{
Side_position_interface::add_support (line_spanner_,i.grob_l_);
add_bound_item (line_spanner_,dynamic_cast<Item*> (i.grob_l_));
SCM defaults = ly_cdr (scm_assoc (ly_symbol2scm ("font-defaults"),
me->paper_l ()->style_sheet_));
- SCM ch = scm_list_n (me->mutable_property_alist_,
- me->immutable_property_alist_,
- defaults,
- SCM_UNDEFINED);
-
+ SCM ch = me->get_property_alist_chain (defaults);
+
return ch;
}
--- /dev/null
+/*
+ Implement storage and manipulation of grob properties.
+ */
+
+#include <string.h>
+#include <math.h>
+
+#include "main.hh"
+#include "input-smob.hh"
+
+#include "group-interface.hh"
+#include "misc.hh"
+#include "paper-score.hh"
+#include "paper-def.hh"
+#include "grob.hh"
+#include "debug.hh"
+#include "spanner.hh"
+#include "item.hh"
+#include "misc.hh"
+#include "item.hh"
+
+/*
+ HASHING_FOR_MUTABLE_PROPS:
+
+
+ plain, -O0 compile
+
+user 0m12.400s
+
+sz == 13, -O0 compile
+
+ xdvi trip
+
+user 0m13.780s
+
+sz == 5
+
+
+user 0m13.000s
+
+sz == 3
+
+
+user 0m13.080s
+
+Hashing doesn't improve the result of grob property lookup, at least
+not with naive hashing. It is possible that the overhead of the
+scm_hash* functions take too much time. One way to solve this is by
+using vector accesses directly, and precompute the hashvalues, similar
+to CACHE_SYMBOLS. That option could only cause slowdowns if the hash
+tables produces weird cache-line trashing.
+
+Second option: we could index immutable props in a hash tab as
+well. This only takes space, since they are immutable no updates are
+needed. This does take a lot of space, since we must duplicate the
+alists (but not the entries).
+
+*/
+
+// #define HASHING_FOR_MUTABLE_PROPS
+
+/*
+ Remove the value associated with KEY, and return it. The result is
+ that a next call will yield SCM_EOL (and not the underlying
+ `basic' property.
+*/
+SCM
+Grob::remove_grob_property (const char* key)
+{
+ SCM val = get_grob_property (key);
+ if (val != SCM_EOL)
+ set_grob_property (key, SCM_EOL);
+ return val;
+}
+
+
+SCM
+Grob::get_property_alist_chain (SCM def) const
+{
+#ifndef HASHING_FOR_MUTABLE_PROPS
+ return scm_list_n (mutable_property_alist_,
+ immutable_property_alist_,
+ def,
+ SCM_UNDEFINED);
+#else
+ SCM chain = gh_list (immutable_property_alist_, def, SCM_UNDEFINED);
+ SCM * velts = SCM_VELTS (mutable_property_alist_);
+ int l = SCM_VECTOR_LENGTH(mutable_property_alist_);
+ for (int i = 0; i < l; i++)
+ {
+ if (gh_pair_p (velts[i]))
+ chain = gh_cons ( velts[i], chain);
+ }
+
+ return chain;
+#endif
+}
+
+
+
+/*
+ This special add_thing routine is slightly more efficient than
+
+ set_prop (name,cons (thing, get_prop (name)))
+
+ since it can reuse the handle returned by scm_assq().
+*/
+void
+Grob::add_to_list_property (SCM sym, SCM thing)
+{
+ SCM handle
+#ifndef HASHING_FOR_MUTABLE_PROPS
+ = scm_sloppy_assq (sym, mutable_property_alist_)
+#else
+ = scm_hashq_get_handle (mutable_property_alist_, sym);
+#endif
+ ;
+ if (handle != SCM_BOOL_F)
+ {
+ gh_set_cdr_x (handle, gh_cons (thing, gh_cdr (handle)));
+ }
+ else
+ {
+ /*
+ There is no mutable prop yet, so create an entry, and put it in front of the
+ mutable prop list.
+ */
+ handle = scm_sloppy_assq (sym, immutable_property_alist_);
+ SCM tail = (handle != SCM_BOOL_F) ? gh_cdr(handle) : SCM_EOL;
+ SCM val = gh_cons (thing, tail);
+#ifndef HASHING_FOR_MUTABLE_PROPS
+ mutable_property_alist_ = gh_cons (gh_cons (sym, val),
+ mutable_property_alist_);
+#else
+ scm_hashq_set_x (mutable_property_alist_, sym, val);
+#endif
+ }
+}
+
+
+extern void check_interfaces_for_property (Grob const *me, SCM sym);
+
+void
+Grob::internal_set_grob_property (SCM s, SCM v)
+{
+ assert (live());
+
+#ifndef NDEBUG
+ if (internal_type_checking_global_b)
+ {
+ assert (type_check_assignment (s, v, ly_symbol2scm ("backend-type?")));
+ check_interfaces_for_property(this, s);
+ }
+#endif
+
+#ifndef HASHING_FOR_MUTABLE_PROPS
+ mutable_property_alist_ = scm_assq_set_x (mutable_property_alist_, s, v);
+#else
+ scm_hashq_set_x (mutable_property_alist_, s, v);
+#endif
+}
+
+
+SCM
+Grob::internal_get_grob_property (SCM sym) const
+{
+#ifndef HASHING_FOR_MUTABLE_PROPS
+ SCM s = scm_sloppy_assq (sym, mutable_property_alist_);
+ if (s != SCM_BOOL_F)
+ return ly_cdr (s);
+#else
+ if (mutable_property_alist_ == SCM_EOL)
+ return SCM_EOL;
+
+ SCM s = scm_hashq_ref (mutable_property_alist_, sym, SCM_EOL);
+ if (s!=SCM_EOL)
+ return s;
+#endif
+
+ s = scm_sloppy_assq (sym, immutable_property_alist_);
+
+#ifndef NDEBUG
+ if (internal_type_checking_global_b && gh_pair_p (s))
+ {
+ assert (type_check_assignment (sym, gh_cdr (s), ly_symbol2scm ("backend-type?")));
+ check_interfaces_for_property(this, sym);
+ }
+#endif
+
+ return (s == SCM_BOOL_F) ? SCM_EOL : ly_cdr (s);
+}
+
+void
+Grob::substitute_mutable_properties (SCM crit, SCM orig)
+{
+ set_break_subsititution(crit);
+#ifndef HASHING_FOR_MUTABLE_PROPS
+ mutable_property_alist_ = substitute_mutable_property_alist (orig);
+#else
+ if (orig == SCM_EOL)
+ {
+ mutable_property_alist_ = SCM_EOL;
+ return ;
+ }
+
+ SCM * src_elts = SCM_VELTS (orig);
+ SCM * dest_elts = SCM_VELTS (mutable_property_alist_);
+ unsigned int l = SCM_VECTOR_LENGTH(mutable_property_alist_);
+ assert (l == SCM_VECTOR_LENGTH(orig));
+ for (unsigned int i = 0; i < l; i++)
+ {
+ dest_elts[i] = substitute_mutable_property_alist (src_elts[i]);
+ }
+#endif
+}
+
+
+bool
+Grob::live () const
+{
+ return immutable_property_alist_ != SCM_EOL;
+}
subclass.
*/
-
+//#define HASHING_FOR_MUTABLE_PROPS
+#define HASH_SIZE 3
#define INFINITY_MSG "Infinity or NaN encountered"
Grob::Grob (SCM basicprops)
smobify_self ();
+#ifdef HASHING_FOR_MUTABLE_PROPS
+ mutable_property_alist_ = scm_c_make_hash_table (HASH_SIZE);
+#endif
+
SCM meta = get_grob_property ("meta");
if (gh_pair_p (meta))
{
SCM ifs = scm_assoc (ly_symbol2scm ("interfaces"), meta);
/*
- do it directly to bypass interface checks.
+ Switch off interface checks for the moment.
*/
- mutable_property_alist_ = gh_cons (gh_cons (ly_symbol2scm ("interfaces"),
- gh_cdr (ifs)),
- mutable_property_alist_);
+ bool itc = internal_type_checking_global_b;
+ internal_type_checking_global_b = false;
+ internal_set_grob_property (ly_symbol2scm ("interfaces"), gh_cdr(ifs));
+ internal_type_checking_global_b = itc;
}
/*
{
original_l_ = (Grob*) &s;
immutable_property_alist_ = s.immutable_property_alist_;
- mutable_property_alist_ = SCM_EOL;
+ mutable_property_alist_ = SCM_EOL;
+
/*
No properties are copied. That is the job of handle_broken_dependencies.
*/
smobify_self ();
-
+#ifdef HASHING_FOR_MUTABLE_PROPS
+ mutable_property_alist_ = scm_c_make_hash_table (HASH_SIZE);
+#endif
}
Grob::~Grob ()
-extern void check_interfaces_for_property (Grob const *me, SCM sym);
-
-void
-Grob::internal_set_grob_property (SCM s, SCM v)
-{
-#ifndef NDEBUG
- if (internal_type_checking_global_b)
- {
- assert (type_check_assignment (s, v, ly_symbol2scm ("backend-type?")));
- check_interfaces_for_property(this, s);
- }
-#endif
-
-
- mutable_property_alist_ = scm_assq_set_x (mutable_property_alist_, s, v);
-}
-
-
-SCM
-Grob::internal_get_grob_property (SCM sym) const
-{
- SCM s = scm_sloppy_assq (sym, mutable_property_alist_);
- if (s != SCM_BOOL_F)
- return ly_cdr (s);
-
- s = scm_sloppy_assq (sym, immutable_property_alist_);
-
-#ifndef NDEBUG
- if (internal_type_checking_global_b && gh_pair_p (s))
- {
- assert (type_check_assignment (sym, gh_cdr (s), ly_symbol2scm ("backend-type?")));
- check_interfaces_for_property(this, sym);
- }
-#endif
-
- return (s == SCM_BOOL_F) ? SCM_EOL : ly_cdr (s);
-}
-
-/*
- Remove the value associated with KEY, and return it. The result is
- that a next call will yield SCM_EOL (and not the underlying
- `basic' property.
-*/
-SCM
-Grob::remove_grob_property (const char* key)
-{
- SCM val = get_grob_property (key);
- if (val != SCM_EOL)
- set_grob_property (key, SCM_EOL);
- return val;
-}
-
MAKE_SCHEME_CALLBACK (Grob,molecule_extent,2);
Molecule *
Grob::get_molecule () const
{
- if (immutable_property_alist_ == SCM_EOL)
+ if (!live())
{
return 0;
Grob * sc = s->broken_into_l_arr_[i];
System * l = sc->line_l ();
- set_break_subsititution (l ? l->self_scm () : SCM_UNDEFINED);
- sc->mutable_property_alist_ =
- substitute_mutable_properties (mutable_property_alist_);
-
+ sc->substitute_mutable_properties (l ? l->self_scm () : SCM_UNDEFINED,
+ mutable_property_alist_);
}
}
System *line = line_l ();
- if (line && common_refpoint (line, X_AXIS) && common_refpoint (line, Y_AXIS))
+ if (live ()
+ && line && common_refpoint (line, X_AXIS) && common_refpoint (line, Y_AXIS))
{
- set_break_subsititution (line ? line->self_scm () : SCM_UNDEFINED);
- mutable_property_alist_ = substitute_mutable_properties (mutable_property_alist_);
+ substitute_mutable_properties (line ? line->self_scm () : SCM_UNDEFINED,
+ mutable_property_alist_);
}
else if (dynamic_cast <System*> (this))
{
- set_break_subsititution (SCM_UNDEFINED);
- mutable_property_alist_ = substitute_mutable_properties (mutable_property_alist_);
+ substitute_mutable_properties (SCM_UNDEFINED, mutable_property_alist_);
}
else
{
void
Grob::handle_prebroken_dependencies ()
{
+ /*
+ Don't do this in the derived method, since we want to keep access to
+ mutable_property_alist_ centralized.
+ */
+ if (original_l_)
+ {
+ Item * it = dynamic_cast<Item*> (this);
+ substitute_mutable_properties (gh_int2scm (it->break_status_dir ()),
+ original_l_->mutable_property_alist_);
+ }
}
Grob*
{
Grob * s = (Grob*) SCM_CELL_WORD_1 (ses);
scm_gc_mark (s->immutable_property_alist_);
- scm_gc_mark (s->mutable_property_alist_);
for (int a =0 ; a < 2; a++)
{
if (s->original_l_)
scm_gc_mark (s->original_l_->self_scm ());
- return s->do_derived_mark ();
+ s->do_derived_mark ();
+ return s->mutable_property_alist_;
}
int
#include "group-interface.hh"
#include "grob.hh"
-
-/*
- This special add_thing routine is slightly more efficient than
-
- set_prop (name,cons (thing, get_prop (name)))
-
- since it can reuse the handle returned by scm_assq().
-*/
-
void
Group_interface::add_thing (Grob*me, SCM sym, SCM thing)
{
-\r SCM handle = scm_sloppy_assq (sym, me->mutable_property_alist_);
- if (handle != SCM_BOOL_F)
- {
- gh_set_cdr_x (handle, gh_cons (thing, gh_cdr (handle)));
-
- }
- else
- {
- /*
- There is no mutable prop yet, so create an entry, and put it in front of the
- mutable prop list.
- */
- handle = scm_sloppy_assq (sym, me->immutable_property_alist_);
- SCM tail = (handle != SCM_BOOL_F) ? gh_cdr(handle) : SCM_EOL;
- me->mutable_property_alist_ = gh_cons (gh_cons (sym, gh_cons (thing, tail)),
- me->mutable_property_alist_);
- }
+ me->add_to_list_property (sym, thing);
}
+
void
Group_interface::add_thing (Grob*me, String name, SCM thing)
{
Basic output object.
*/
class Grob {
-public:
+private:
SCM immutable_property_alist_;
SCM mutable_property_alist_;
-
+
+ void substitute_mutable_properties(SCM,SCM);
+public:
Grob *original_l_;
/**
*/
SCM internal_get_grob_property (SCM) const;
void internal_set_grob_property (SCM, SCM val);
-
+ void add_to_list_property (SCM, SCM);
void warning (String)const;
void programming_error (String)const;
Molecule * get_molecule () const;
SCM get_uncached_molecule () const;
-
+
+ SCM get_property_alist_chain (SCM) const;
void suicide ();
+ bool live () const;
DECLARE_SCHEME_CALLBACK (preset_extent, (SCM smob, SCM axis));
DECLARE_SCHEME_CALLBACK (point_dimension_callback, (SCM smob, SCM axis));
Grob*common_refpoint_of_array (Link_array<Grob> const&, Grob * , Axis a);
void set_break_subsititution (SCM criterion);
-SCM substitute_mutable_properties (SCM alist);
+SCM substitute_mutable_property_alist (SCM alist);
#endif // STAFFELEM_HH
void add_bound_item (Spanner*, Grob*);
-void extend_spanner_over_elements (Grob* span);
#endif
{
broken_to_drul_[LEFT] = broken_to_drul_[RIGHT]=0;
Group_interface::add_thing (this, ly_symbol2scm ("interfaces"), ly_symbol2scm ("item-interface"));
-
}
/**
void
Item::handle_prebroken_dependencies ()
{
- if (original_l_)
- {
- set_break_subsititution (gh_int2scm (break_status_dir ()));
- mutable_property_alist_ = substitute_mutable_properties(original_l_->mutable_property_alist_);
- }
+ Grob::handle_prebroken_dependencies ();
/*
Can't do this earlier, because try_visibility_lambda () might set
TODO:
- handle break-visibility the item itself iso. breakstatusdir, so
- the function can do more complicated things.
+ give the item to break-visibility itself, so the function can do
+ more complicated things.
*/
SCM vis = get_grob_property ("break-visibility");
if (gh_procedure_p (vis))
"item-interface",
"
-Grobs can also be distinguished in their role in the horizontal spacing.
+Grobs can be distinguished in their role in the horizontal spacing.
Many grobs define constraints on the spacing by their sizes. For
example, note heads, clefs, stems, and all other symbols with a fixed
shape. These grobs form a subtype called @code{Item}.
ADD_SCM_INIT_FUNC (funcs, init_functions);
SCM
-ly_deep_copy (SCM l)
+ly_deep_copy (SCM src)
{
- if (gh_pair_p (l))
+ if (gh_pair_p (src))
{
- return gh_cons (ly_deep_copy (ly_car (l)), ly_deep_copy (ly_cdr (l)));
+ return gh_cons (ly_deep_copy (ly_car (src)), ly_deep_copy (ly_cdr (src)));
+ }
+ else if (gh_vector_p (src))
+ {
+ int l = SCM_VECTOR_LENGTH (src);
+ SCM nv = scm_c_make_vector (l, SCM_UNDEFINED);
+ for (int i =0 ; i< l ; i++)
+ {
+ SCM si = gh_int2scm (i);
+ scm_vector_set_x (nv, si, ly_deep_copy (scm_vector_ref (src, si)));
+ }
}
else
- return l;
+ return src;
+
+ return src;
}
Item *
Note_spacing::left_column (Grob *me)
{
- if (me->immutable_property_alist_ == SCM_EOL)
+ if (!me->live())
return 0;
return dynamic_cast<Item*> (me)->column_l ();
Item *
Note_spacing::right_column (Grob*me)
{
- /*
- ugh. should have generic is_live() method?
- */
- if (me->immutable_property_alist_ == SCM_EOL)
+ if (!me->live())
return 0;
SCM right = me->get_grob_property ("right-items");
suicide?
*/
if (p->line_spanner_
- && p->line_spanner_->immutable_property_alist_ == SCM_EOL)
+ && !p->line_spanner_->live())
p->line_spanner_ = 0;
if (p->line_spanner_)
typeset_all ();
}
if (p->bracket_p_
- && p->bracket_p_->immutable_property_alist_ == SCM_EOL)
+ && !p->bracket_p_->live())
p->bracket_p_ = 0;
if (p->bracket_p_)
{
Handle suicide.
*/
if (p->finished_line_spanner_
- && p->finished_line_spanner_->immutable_property_alist_ == SCM_EOL)
+ && !p->finished_line_spanner_->live ())
p->finished_line_spanner_ = 0;
if (p->finished_bracket_p_
- && p->finished_bracket_p_->immutable_property_alist_ == SCM_EOL)
+ && !p->finished_bracket_p_->live())
p->finished_bracket_p_ = 0;
/* don't warn for empty/suicided spanners,
it makes real warningsinvisible.
maybe should be junked earlier? */
- if (elem_p->immutable_property_alist_ == SCM_EOL)
+ if (!elem_p->live())
; // gdb hook
else
elem_p->warning (_f ("unbound spanner `%s'", s->name ().ch_C ()));
if (Staff_spacing::has_interface (gi.grob_l_))
{
Pointer_group_interface::add_grob (command_column_l_,
- ly_symbol2scm ("spacing-wishes"),
- gi.grob_l_);
+ ly_symbol2scm ("spacing-wishes"),
+ gi.grob_l_);
}
if (Note_spacing::has_interface (gi.grob_l_))
{
Spaceable_grob::remove_interface (Grob*me)
{
me->remove_grob_property ("minimum-distances");
+ me->remove_grob_property ("spacing-wishes");
me->remove_grob_property ("ideal-distances");
}
ADD_INTERFACE (Spaceable_grob,"spaceable-grob-interface",
"A grob (a Paper_column) that takes part in the
spacing problem. ",
- "measure-length penalty minimum-distances ideal-distances
+ "measure-length spacing-wishes penalty minimum-distances ideal-distances
left-neighbors right-neighbors");
sp->set_bound (RIGHT, it);
}
-/*
- Extends EXTREMAL_PAIR to include IT
- */
-static void
-extend_spanner_over_item (Item *it, SCM extremal_pair)
-{
- if (!it)
- return;
- Item * col = it->column_l ();
- Item * i1 = dynamic_cast<Item*> (unsmob_grob (ly_car (extremal_pair)));
- Item * i2 = dynamic_cast<Item*> (unsmob_grob (ly_cdr (extremal_pair)));
- int r = Paper_column::rank_i (col);
- if (!i1 || r < Paper_column::rank_i (i1->column_l ()))
- {
- gh_set_car_x (extremal_pair, it->self_scm ());
- }
- if (!i2 || r > Paper_column::rank_i (i2->column_l ()))
- {
- gh_set_cdr_x (extremal_pair, it->self_scm ());
- }
-}
-
-/*
- Extends EXTREMAL_PAIR to include every grob in VALUE
- */
-static void
-extend_spanner_over_elements (SCM value, SCM extremal_pair)
-{
- if (gh_pair_p (value))
- {
- extend_spanner_over_elements (ly_car (value), extremal_pair);
- extend_spanner_over_elements (ly_cdr (value), extremal_pair);
- }
- else if (unsmob_grob (value))
- {
- if (Spanner * sp = dynamic_cast<Spanner*> (unsmob_grob (value)))
- {
- extend_spanner_over_item (sp->get_bound (LEFT), extremal_pair);
- extend_spanner_over_item (sp->get_bound (RIGHT), extremal_pair);
- }
- else if (Item * it= dynamic_cast<Item*> (unsmob_grob (value)))
- extend_spanner_over_item (it, extremal_pair);
- }
-}
-
-
-/*
- Make sure that the left and right bounds encompasses all objects it
- points to.
-
- TODO: maybe be more specific. Most probably fucks up if someone sets
- a pointer to the staff symbol in S
-*/
-void
-extend_spanner_over_elements (Grob*s)
-{
- Spanner*sp = dynamic_cast<Spanner*> (s);
-
- SCM s1 = sp->get_bound (LEFT) ? sp->get_bound (LEFT)->self_scm () : SCM_EOL;
- SCM s2 = sp->get_bound (RIGHT) ? sp->get_bound (RIGHT)->self_scm () : SCM_EOL;
-
- SCM pair = gh_cons (s1,s2);
- extend_spanner_over_elements (sp->mutable_property_alist_, pair);
-
- Grob *p1 = unsmob_grob (ly_car (pair));
- Grob* p2 = unsmob_grob (ly_cdr (pair));
- sp->set_bound (LEFT,p1);
- sp->set_bound (RIGHT, p2);
-}
-
MAKE_SCHEME_CALLBACK (Spanner,set_spacing_rods,1);
SCM
/*
TODO: make the stem start a direction ?
-
*/
+
+
+
if (to_boolean (me->get_grob_property ("avoid-note-head")))
{
- y1 = Staff_symbol_referencer::position_f (last_head (me));
+ Grob * lh = last_head (me);
+ if (!lh)
+ return SCM_EOL;
+ y1 = Staff_symbol_referencer::position_f (lh);
}
else
{
- y1 = Staff_symbol_referencer::position_f (first_head (me));
+ Grob * lh = first_head (me);
+ if (!lh)
+ return SCM_EOL;
+ y1 = Staff_symbol_referencer::position_f (lh);
}
Real y2 = stem_end_position (me);
mol.add_molecule (end);
SCM text = me->get_grob_property ("text");
- SCM properties = scm_list_n (me->mutable_property_alist_,
- me->immutable_property_alist_,SCM_UNDEFINED);
+ SCM properties = me->get_property_alist_chain (SCM_EOL);
+
Molecule num = Text_item::text2molecule (me, text, properties);
mol.add_at_edge (X_AXIS, LEFT, num, - num.extent (X_AXIS).length ()
)
)
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-; Prefatory matter: break align item.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Spacing constants
-;;
-;; rules for this spacing are much more complicated than this.
-;; See [Wanske] page 126 -- 134, [Ross] pg 143 -- 147
-;;
-
-;; documentme: difference between extra-space and minimum-space-pair
-
-;; (Measured in staff space)
-(define default-break-align-space-alist
- '(
- ((none Instrument_name) . (extra-space 1.0))
- ((none Left_edge_item) . (extra-space 0.0))
- ((none Ambitus) . (extra-space 1.0))
- ((none Clef_item) . (minimum-space-pair 1.0))
- ((none Staff_bar) . (minimum-space-pair 0.0))
- ((none Clef_item) . (minimum-space-pair 1.0))
- ((none Key_item) . (minimum-space-pair 0.5))
- ((none Time_signature) . (extra-space 0.0))
- ((none Breathing_sign) . (minimum-space-pair 0.0))
-
-
-
-
-
-
- ((none begin-of-note) . (minimum-space-pair 1.5))
-
- )
-)
-
@code{extra-offset} is added just before `printing' the grob, so the
typesetting engine is completely oblivious to it.
")
-(grob-property-description 'extra-space number-pair? "pair of distances (cons LEFT RIGHT).")
(grob-property-description 'extremity-offset-alist list? "an alist (attachment stem-dir*dir slur-dir*dir) -> offset. The offset adds to the centre of the notehead, or stem.")
(grob-property-description 'extremity-rules list? "an alist (procedure
(grob-property-description 'space-function procedure? "return interbeam space given Beam grob and multiplicity.")
(grob-property-description 'spacing-increment number? "Add this much space for a doubled duration. Typically, the width of a note head. See also @ref{spacing-spanner-interface}.")
+(grob-property-description 'spacing-wishes grob-list? "List of note spacing or staff spacing objects.")
(grob-property-description 'spacing-procedure procedure? "procedure
taking grob as argument. This is called after
before-line-breaking-callback, but before the actual line breaking