]> git.donarmstrong.com Git - lilypond.git/commitdiff
''
authorHan-Wen Nienhuys <hanwen@xs4all.nl>
Wed, 3 Jul 2002 11:57:23 +0000 (11:57 +0000)
committerHan-Wen Nienhuys <hanwen@xs4all.nl>
Wed, 3 Jul 2002 11:57:23 +0000 (11:57 +0000)
22 files changed:
ChangeLog
lily/align-interface.cc
lily/break-align-interface.cc
lily/break-substitution.cc
lily/dynamic-engraver.cc
lily/font-interface.cc
lily/grob-property.cc [new file with mode: 0644]
lily/grob.cc
lily/group-interface.cc
lily/include/grob.hh
lily/include/spanner.hh
lily/item.cc
lily/lily-guile.cc
lily/note-spacing.cc
lily/piano-pedal-engraver.cc
lily/score-engraver.cc
lily/spaceable-grob.cc
lily/spanner.cc
lily/stem.cc
lily/volta-bracket.cc
scm/basic-properties.scm
scm/grob-property-description.scm

index 1d3cc75c9720ac70998240e84c2bdbff3a07e5f7..ea09d5e6ece8b2844aff59a7a40943b60d3cde16 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+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
index 6158a3720f9422bdc3624691e9c21cd53fa99ff2..5bb8c333588317dc1524ffae831cea2c19bdf78f 100644 (file)
@@ -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<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);          
        }
@@ -290,6 +272,3 @@ struct Foobar
 {
   bool has_interface (Grob*);
 };
-ADD_INTERFACE (Foobar, "aligned-interface",
-  "read by align-interface",
-  "minimum-space-pair extra-space");
index 76fd54a6f3bddf8de3e257d6ef1a6829b8f03fcb..a4205c00c77dc6928294d94b7c151773f779b454 100644 (file)
@@ -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");
 
index 4f560e85cd1c2b286b8e9106a0fc31e2a2442cb7..563eda0939ea5a09ddf5db893be8c4c876f38227 100644 (file)
@@ -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;
 }
+
+
index 54e7df9149909cb2ecdde30d5cd4836501c8a06d..f51dfb20fc32a6ed7deac3b356f7e0b29cca179c 100644 (file)
@@ -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<Item*> (i.grob_l_));
index 57cf99679e72d511c813879f4e68c18dc2a31917..28a88c546935d6395a844cb23c01bf0d17a5ec55 100644 (file)
@@ -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 (file)
index 0000000..dfeee30
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+  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;
+}
index 6ae709739f0bfd8612089fde9e690b744e15e29c..6caceb624a462042c883099a369177b7db877c61 100644 (file)
@@ -39,7 +39,8 @@ remove dynamic_cast<Spanner,Item> 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 <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
     {
@@ -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<Item*> (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
index c7991793faece177e63b7fea8fe6161dfd9c5dac..4b4fd9c4b1c1260da6349e4b019de466859a793d 100644 (file)
@@ -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)
 {
-\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)
 {
index e8a501bc699bf02be8bf6068713964863ccf8495..71921452e368a6488d522caffe60ac2e4738e63d 100644 (file)
@@ -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<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
index 4327653e00f8693afc8c4c1d2fedf2f7b121ccf5..ecc90465cccff35b996e0faf3735a694fa9ad3d4 100644 (file)
@@ -65,7 +65,6 @@ protected:
 
 
 void add_bound_item (Spanner*, Grob*);
-void extend_spanner_over_elements (Grob*  span);
 
 
 #endif
index 94a12e92c3d1c46af6c8f16ed77184c146bace60..a16253825a282747a611b598e606ad3e92c871f0 100644 (file)
@@ -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}.
index cf2e275027e91f0166753805114a0c476546cfe4..89bf7e82b8623c4fe60995c48342c4f2719a7578 100644 (file)
@@ -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;
 }
 
 
index 95ba49aa64a7a271f06dd4261dddb62ace9e0cbf..afd1a0962f91bff6545127dd452c698607befb65 100644 (file)
@@ -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<Item*> (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");
index 14bfb4e3199adae68b594ca3f2f2cafa3ec35e54..666cda769e3ed5842da8d0428b15f60bab8ca075 100644 (file)
@@ -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;
 
 
index bd47e1fa274f7b72b0567f1151af696c7c139ba3..15c50847ee6ae92b9ebb70c85f948571d6fcfde2 100644 (file)
@@ -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_))
     {
index 0f80197c4b7379be32b7b1e6cf6c86bd086c31a2..542838c7c14a03eb106e6661030720a82316824e 100644 (file)
@@ -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");
 
index 7754f9f5ed6e59338d171b8acb8f8f4954bebfba..0c65019c4f2fef34e2532933b9ba6889be7cf1b3 100644 (file)
@@ -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<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
index 895caf999cab661b59a1b9e912d1cbc8c9dbd202..b80418aa89c73abb65593a337205510f513b0aff 100644 (file)
@@ -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);
index d0af30da3e37aa6f4afa5778b6cf260cf1b76a17..1c3d2fd1a45c378ecd14593a58330dcbc4159a70 100644 (file)
@@ -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 ()
index d3823ca4fbc4e0e8402714a01ad1c1a05c298665..b9f2683e46ab8b4ceb06c6998c08f2ec09055241 100644 (file)
      )
    )
      
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;  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))
-
-   )
-)
-
index 207e0ddf7c8a5b3b82f2985fe8f7bc8100287e4f..0c6e6618a7022b42491af58245f5b220816e6079 100644 (file)
@@ -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