]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/dimension-cache.cc
release: 1.3.40
[lilypond.git] / lily / dimension-cache.cc
index 6713e82b191276fba92d2fac48e698988e6c3f93..ad4c630c0a38ad36fa5e10f12bdef3dff3a1d5ad 100644 (file)
@@ -3,17 +3,25 @@
   
   source file of the GNU LilyPond music typesetter
   
-  (c) 1998 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+  (c) 1998--2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
  */
+#include <math.h>
+#include "warn.hh"
 
 #include "dimension-cache.hh"
 #include "parray.hh"
+#include "score-element.hh"
+
 
 Dimension_cache::Dimension_cache (Dimension_cache const &d)
 {
   init();
-  empty_b_ = d.empty_b_;
-  offset_ = d.offset_; //let's hope others will copy  the refpoint appropriately. 
+  extent_callback_l_ = d.extent_callback_l_;
+  basic_offset_ = d.basic_offset_;
+  extra_offset_ = d.extra_offset_;
+  off_valid_b_ = d.off_valid_b_;
+  off_callbacks_ = d.off_callbacks_;
+  parent_l_ = d.parent_l_;  
 }
 
 Dimension_cache::Dimension_cache ()
@@ -24,129 +32,113 @@ Dimension_cache::Dimension_cache ()
 void
 Dimension_cache::init()
 {
-  offset_ =0.0;
+  extent_callback_l_ =0;
+  basic_offset_ =0.0;
+  extra_offset_ =0.0;
+  
   elt_l_ = 0;
   dim_.set_empty ();
   parent_l_ =0;
   valid_b_ = false;
-  empty_b_ = false;
+  off_valid_b_ = false;
 }
 
 
 void
-Dimension_cache::invalidate ()
-{
-  valid_b_ = false;
-  invalidate_dependencies ();
-}
-
-void
-Dimension_cache::invalidate_dependencies ()
-{
-  for (int i=0; i < dependencies_l_arr_.size (); i++)
-    {
-      Dimension_cache * g = dependencies_l_arr_[i];
-      if (g->valid_b_)
-       {
-         g->invalidate ();
-       }
-    }
-}
-
-void
-Dimension_cache::set_offset (Real x)
+Dimension_cache::translate (Real x)
 {
-  invalidate_dependencies ();
-  offset_ = x;
+  extra_offset_ += x;
 }
 
-void
-Dimension_cache::translate (Real x)
+Real
+Dimension_cache::relative_coordinate (Dimension_cache *refp) const
 {
-  invalidate_dependencies ();
-  offset_ += x;
+  if (refp == this)
+    return 0.0;
+
+  /*
+    We catch PARENT_L_ == nil case with this, but we crash if we did
+    not ask for the absolute coordinate (ie. REFP == nil.)
+    
+   */
+  if (refp == parent_l_)
+    return get_offset ();
+  else
+    return get_offset () + parent_l_->relative_coordinate (refp);
 }
 
-
-Real
-Dimension_cache::absolute_coordinate () const
+Axis
+Dimension_cache::axis () const
 {
-  Real r = offset_;
-  for (Dimension_cache * c = parent_l_;
-       c; c = c->parent_l_)
-    r += c->offset_;
-  return r;
+  if (elt_l_-> dim_cache_[X_AXIS] == this)
+    return X_AXIS;
+  else
+    return Y_AXIS;
 }
 
 Real
-Dimension_cache::relative_coordinate (Dimension_cache *d) const
+Dimension_cache::get_offset () const
 {
-  Real r =0.0;
-
-  for (Dimension_cache* c = parent_l_;
-       c != d;
-       c = c->parent_l_)
-    r +=  c->offset_;
-  return r;
+  Dimension_cache *me = (Dimension_cache*) this;
+  while (off_callbacks_.size ())
+    {
+      Offset_cache_callback c = me->off_callbacks_[0];
+      me->off_callbacks_.del (0);
+      Real r =  (*c) (me);
+      if (isinf (r) || isnan (r))
+       {
+         r = 0.0;
+         programming_error ("Infinity or NaN encountered");
+       }
+      me->basic_offset_ +=r;
+    }
+  return basic_offset_ + extra_offset_;
 }
 
 Dimension_cache *
-Dimension_cache::common_group (Dimension_cache const* s) const
+Dimension_cache::common_refpoint (Dimension_cache const* s) const
 {
-  Link_array<Dimension_cache const> my_groups;
-  for (Dimension_cache const *c = this;
-       c ; c = c->parent_l_)
-    my_groups.push (c);
-  
-  
-  Dimension_cache const *common=0;
-  
-  for (Dimension_cache const * d = s;
-       !common && d;
-       d = d->parent_l_)
-    common = my_groups.find_l (d);
-
-  return (Dimension_cache*)common;
+  /*
+    I don't like the quadratic aspect of this code. Maybe this should
+    be rewritten some time, but the largest chain of parents might be
+    10 high or so, so it shouldn't be a real issue. */
+  for (Dimension_cache const *c = this; c; c = c->parent_l_)
+    for (Dimension_cache const * d = s; d; d = d->parent_l_)
+      if (d == c)
+       return (Dimension_cache*)d;
+
+  return 0;
 }
 
-
-
-void
-Dimension_cache::set_empty (bool b)
-{
-  if (empty_b_ != b)
-    {
-      empty_b_ = b;
-      if (!empty_b_)
-       invalidate ();
-    }
-}  
-
-void
-Dimension_cache::set_dim (Interval v)
+Interval
+Dimension_cache::point_dimension_callback (Dimension_cache const* )
 {
-  dim_ = v;
-  valid_b_ = true;
+  return Interval (0,0);
 }
-  
 
 Interval
 Dimension_cache::get_dim () const
 {
   Interval r;
-  if (empty_b_)
+  Dimension_cache *nc = ((Dimension_cache*)this);
+  if (!extent_callback_l_)
+    {
+      nc->dim_.set_empty ();
+    }
+  else if (!valid_b_)
     {
-      r.set_empty ();
-      return r;
+      nc->dim_= (*extent_callback_l_ ) (nc);
+      nc->valid_b_ = true;
     }
-      
-  assert (valid_b_);
 
   r=dim_;
-  if (!r.empty_b()) // float exception on DEC Alpha
-    r += offset_;
-
   return r;
 }
 
+void
+Dimension_cache::set_extent_callback (Dim_cache_callback c)
+{
+  extent_callback_l_ =c;
+}
+