From: Han-Wen Nienhuys Date: Wed, 3 Jul 2002 11:57:23 +0000 (+0000) Subject: '' X-Git-Tag: release/1.5.65~4 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=cf33d3709d3b5028fa9c208aa490ce066960ad5c;p=lilypond.git '' --- diff --git a/ChangeLog b/ChangeLog index 1d3cc75c97..ea09d5e6ec 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2002-07-03 Han-Wen + + * 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 * stepmake/aclocal.m4 (STEPMAKE_GET_VERSION): Workaround for diff --git a/lily/align-interface.cc b/lily/align-interface.cc index 6158a3720f..5bb8c33358 100644 --- a/lily/align-interface.cc +++ b/lily/align-interface.cc @@ -88,7 +88,7 @@ Align_interface::align_to_fixed_distance (Grob *me , Axis a) && 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); } @@ -110,7 +110,7 @@ Align_interface::align_to_fixed_distance (Grob *me , Axis a) /* 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 @@ -155,24 +155,6 @@ Align_interface::align_elements_to_extents (Grob * me, Axis a) { Grob *e =dynamic_cast (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); } @@ -290,6 +272,3 @@ struct Foobar { bool has_interface (Grob*); }; -ADD_INTERFACE (Foobar, "aligned-interface", - "read by align-interface", - "minimum-space-pair extra-space"); diff --git a/lily/break-align-interface.cc b/lily/break-align-interface.cc index 76fd54a6f3..a4205c00c7 100644 --- a/lily/break-align-interface.cc +++ b/lily/break-align-interface.cc @@ -228,6 +228,10 @@ of the associated space. The space definition is either (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"); diff --git a/lily/break-substitution.cc b/lily/break-substitution.cc index 4f560e85cd..563eda0939 100644 --- a/lily/break-substitution.cc +++ b/lily/break-substitution.cc @@ -77,20 +77,19 @@ substitute_grob (Grob *sc) /* - 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) { @@ -100,6 +99,17 @@ 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)) { /* @@ -160,7 +170,7 @@ SCM grob_list_p; /* 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 @@ -171,7 +181,7 @@ SCM grob_list_p; 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?"); @@ -195,3 +205,5 @@ substitute_mutable_properties (SCM alist) return l; } + + diff --git a/lily/dynamic-engraver.cc b/lily/dynamic-engraver.cc index 54e7df9149..f51dfb20fc 100644 --- a/lily/dynamic-engraver.cc +++ b/lily/dynamic-engraver.cc @@ -291,7 +291,7 @@ Dynamic_engraver::finalize () typeset_all (); if (line_spanner_ - && line_spanner_->immutable_property_alist_ == SCM_EOL) + && !line_spanner_->live()) line_spanner_ = 0; if (line_spanner_) { @@ -300,7 +300,7 @@ Dynamic_engraver::finalize () } if (cresc_p_ - && cresc_p_->immutable_property_alist_ == SCM_EOL) + && !cresc_p_->live()) cresc_p_ = 0; if (cresc_p_) { @@ -320,10 +320,10 @@ Dynamic_engraver::typeset_all () 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_) @@ -355,7 +355,7 @@ Dynamic_engraver::typeset_all () /* 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 @@ -396,7 +396,7 @@ Dynamic_engraver::acknowledge_grob (Grob_info i) { 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 (i.grob_l_)); diff --git a/lily/font-interface.cc b/lily/font-interface.cc index 57cf99679e..28a88c5469 100644 --- a/lily/font-interface.cc +++ b/lily/font-interface.cc @@ -41,11 +41,8 @@ Font_interface::font_alist_chain (Grob *me) 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; } diff --git a/lily/grob-property.cc b/lily/grob-property.cc new file mode 100644 index 0000000000..dfeee301da --- /dev/null +++ b/lily/grob-property.cc @@ -0,0 +1,222 @@ +/* + Implement storage and manipulation of grob properties. + */ + +#include +#include + +#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; +} diff --git a/lily/grob.cc b/lily/grob.cc index 6ae709739f..6caceb624a 100644 --- a/lily/grob.cc +++ b/lily/grob.cc @@ -39,7 +39,8 @@ remove dynamic_cast and put this code into respective subclass. */ - +//#define HASHING_FOR_MUTABLE_PROPS +#define HASH_SIZE 3 #define INFINITY_MSG "Infinity or NaN encountered" Grob::Grob (SCM basicprops) @@ -62,17 +63,22 @@ 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; } /* @@ -120,8 +126,9 @@ Grob::Grob (Grob const&s) { 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. */ @@ -131,7 +138,9 @@ Grob::Grob (Grob const&s) smobify_self (); - +#ifdef HASHING_FOR_MUTABLE_PROPS + mutable_property_alist_ = scm_c_make_hash_table (HASH_SIZE); +#endif } Grob::~Grob () @@ -143,58 +152,6 @@ 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); @@ -272,7 +229,7 @@ Grob::calculate_dependencies (int final, int busy, SCM funcname) Molecule * Grob::get_molecule () const { - if (immutable_property_alist_ == SCM_EOL) + if (!live()) { return 0; @@ -381,25 +338,23 @@ Grob::handle_broken_dependencies () 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 (this)) { - set_break_subsititution (SCM_UNDEFINED); - mutable_property_alist_ = substitute_mutable_properties (mutable_property_alist_); + substitute_mutable_properties (SCM_UNDEFINED, mutable_property_alist_); } else { @@ -440,6 +395,16 @@ Grob::suicide () 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 (this); + substitute_mutable_properties (gh_int2scm (it->break_status_dir ()), + original_l_->mutable_property_alist_); + } } Grob* @@ -756,7 +721,6 @@ Grob::mark_smob (SCM ses) { 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++) { @@ -776,7 +740,8 @@ Grob::mark_smob (SCM ses) 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 diff --git a/lily/group-interface.cc b/lily/group-interface.cc index c7991793fa..4b4fd9c4b1 100644 --- a/lily/group-interface.cc +++ b/lily/group-interface.cc @@ -9,37 +9,13 @@ #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) { - 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) { diff --git a/lily/include/grob.hh b/lily/include/grob.hh index e8a501bc69..71921452e3 100644 --- a/lily/include/grob.hh +++ b/lily/include/grob.hh @@ -37,10 +37,12 @@ typedef void (Grob::*Grob_method_pointer) (void); 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_; /** @@ -69,7 +71,7 @@ public: */ 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; @@ -110,8 +112,10 @@ public: 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)); @@ -160,7 +164,7 @@ Grob*common_refpoint_of_list (SCM elt_list, Grob * , Axis a); Grob*common_refpoint_of_array (Link_array 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 diff --git a/lily/include/spanner.hh b/lily/include/spanner.hh index 4327653e00..ecc90465cc 100644 --- a/lily/include/spanner.hh +++ b/lily/include/spanner.hh @@ -65,7 +65,6 @@ protected: void add_bound_item (Spanner*, Grob*); -void extend_spanner_over_elements (Grob* span); #endif diff --git a/lily/item.cc b/lily/item.cc index 94a12e92c3..a16253825a 100644 --- a/lily/item.cc +++ b/lily/item.cc @@ -21,7 +21,6 @@ Item::Item (SCM s) { broken_to_drul_[LEFT] = broken_to_drul_[RIGHT]=0; Group_interface::add_thing (this, ly_symbol2scm ("interfaces"), ly_symbol2scm ("item-interface")); - } /** @@ -143,11 +142,7 @@ Item::break_status_dir () const 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 @@ -155,8 +150,8 @@ Item::handle_prebroken_dependencies () 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)) @@ -200,7 +195,7 @@ ADD_INTERFACE(Item, "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}. diff --git a/lily/lily-guile.cc b/lily/lily-guile.cc index cf2e275027..89bf7e82b8 100644 --- a/lily/lily-guile.cc +++ b/lily/lily-guile.cc @@ -524,14 +524,26 @@ init_functions () 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; } diff --git a/lily/note-spacing.cc b/lily/note-spacing.cc index 95ba49aa64..afd1a0962f 100644 --- a/lily/note-spacing.cc +++ b/lily/note-spacing.cc @@ -119,7 +119,7 @@ Note_spacing::get_spacing (Grob *me, Item* right_col, Item * Note_spacing::left_column (Grob *me) { - if (me->immutable_property_alist_ == SCM_EOL) + if (!me->live()) return 0; return dynamic_cast (me)->column_l (); @@ -136,10 +136,7 @@ prune RIGHT-ITEMS. 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"); diff --git a/lily/piano-pedal-engraver.cc b/lily/piano-pedal-engraver.cc index 14bfb4e319..666cda769e 100644 --- a/lily/piano-pedal-engraver.cc +++ b/lily/piano-pedal-engraver.cc @@ -388,7 +388,7 @@ Piano_pedal_engraver::finalize () 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_) @@ -397,7 +397,7 @@ Piano_pedal_engraver::finalize () 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_) { @@ -435,10 +435,10 @@ Piano_pedal_engraver::typeset_all () 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; diff --git a/lily/score-engraver.cc b/lily/score-engraver.cc index bd47e1fa27..15c50847ee 100644 --- a/lily/score-engraver.cc +++ b/lily/score-engraver.cc @@ -175,7 +175,7 @@ Score_engraver::typeset_all () /* 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 ())); @@ -299,8 +299,8 @@ Score_engraver::acknowledge_grob (Grob_info gi) 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_)) { diff --git a/lily/spaceable-grob.cc b/lily/spaceable-grob.cc index 0f80197c4b..542838c7c1 100644 --- a/lily/spaceable-grob.cc +++ b/lily/spaceable-grob.cc @@ -78,6 +78,7 @@ void Spaceable_grob::remove_interface (Grob*me) { me->remove_grob_property ("minimum-distances"); + me->remove_grob_property ("spacing-wishes"); me->remove_grob_property ("ideal-distances"); } @@ -86,6 +87,6 @@ Spaceable_grob::remove_interface (Grob*me) 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"); diff --git a/lily/spanner.cc b/lily/spanner.cc index 7754f9f5ed..0c65019c4f 100644 --- a/lily/spanner.cc +++ b/lily/spanner.cc @@ -320,76 +320,6 @@ add_bound_item (Spanner* sp, Grob*it) 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 (unsmob_grob (ly_car (extremal_pair))); - Item * i2 = dynamic_cast (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 (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 (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 (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 diff --git a/lily/stem.cc b/lily/stem.cc index 895caf999c..b80418aa89 100644 --- a/lily/stem.cc +++ b/lily/stem.cc @@ -642,15 +642,23 @@ Stem::brew_molecule (SCM smob) /* 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); diff --git a/lily/volta-bracket.cc b/lily/volta-bracket.cc index d0af30da3e..1c3d2fd1a4 100644 --- a/lily/volta-bracket.cc +++ b/lily/volta-bracket.cc @@ -104,8 +104,8 @@ Volta_bracket_interface::brew_molecule (SCM smob) 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 () diff --git a/scm/basic-properties.scm b/scm/basic-properties.scm index d3823ca4fb..b9f2683e46 100644 --- a/scm/basic-properties.scm +++ b/scm/basic-properties.scm @@ -46,37 +46,3 @@ ) ) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; 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)) - - ) -) - diff --git a/scm/grob-property-description.scm b/scm/grob-property-description.scm index 207e0ddf7c..0c6e6618a7 100644 --- a/scm/grob-property-description.scm +++ b/scm/grob-property-description.scm @@ -176,7 +176,6 @@ mean centre distance weighted per note @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 @@ -358,6 +357,7 @@ minimum-space or extra-space.") (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