gnash-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Gnash-commit] /srv/bzr/gnash/trunk r10765: Document movie_root::errorIn


From: Benjamin Wolsey
Subject: [Gnash-commit] /srv/bzr/gnash/trunk r10765: Document movie_root::errorInterface(). Tidy up snappingrange a bit.
Date: Fri, 03 Apr 2009 20:45:30 +0200
User-agent: Bazaar (1.5)

------------------------------------------------------------
revno: 10765
committer: Benjamin Wolsey <address@hidden>
branch nick: trunk
timestamp: Fri 2009-04-03 20:45:30 +0200
message:
  Document movie_root::errorInterface(). Tidy up snappingrange a bit.
modified:
  gui/gui.cpp
  libbase/snappingrange.h
  libcore/movie_root.h
    ------------------------------------------------------------
    revno: 10762.2.1
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Thu 2009-04-02 14:44:14 +0200
    message:
      Make certain members mutable for lazy finalization instead of 
const_casting.
      Add some const correctness.
    modified:
      libbase/snappingrange.h
    ------------------------------------------------------------
    revno: 10762.2.2
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Thu 2009-04-02 14:52:05 +0200
    message:
      Further cleanups.
    modified:
      libbase/snappingrange.h
    ------------------------------------------------------------
    revno: 10762.2.3
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Thu 2009-04-02 15:01:05 +0200
    message:
      Fix warning.
    modified:
      libbase/snappingrange.h
    ------------------------------------------------------------
    revno: 10762.2.4
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Thu 2009-04-02 18:12:46 +0200
    message:
      Reduce a bit more with boost::bind and algorithms.
    modified:
      libbase/snappingrange.h
    ------------------------------------------------------------
    revno: 10762.2.5
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Thu 2009-04-02 19:55:20 +0200
    message:
      Write our own function objects, as it's easier than using bind and mem_fn.
    modified:
      libbase/snappingrange.h
    ------------------------------------------------------------
    revno: 10762.2.6
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Fri 2009-04-03 08:44:59 +0200
    message:
      Tidy up.
    modified:
      gui/gui.cpp
      libbase/snappingrange.h
    ------------------------------------------------------------
    revno: 10762.2.7
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Fri 2009-04-03 09:43:55 +0200
    message:
      Typo.
    modified:
      libbase/snappingrange.h
    ------------------------------------------------------------
    revno: 10762.2.8
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Fri 2009-04-03 20:13:27 +0200
    message:
      Remove extra spaces.
    modified:
      libbase/snappingrange.h
=== modified file 'gui/gui.cpp'
--- a/gui/gui.cpp       2009-04-03 09:18:40 +0000
+++ b/gui/gui.cpp       2009-04-03 18:45:30 +0000
@@ -712,12 +712,12 @@
                changed_ranges.growBy(40.0f / _xscale);
                
                // optimize ranges
-               changed_ranges.combine_ranges();
+               changed_ranges.combineRanges();
                
        }
-
-       if (redraw_flag)     // TODO: Remove this and want_redraw to avoid 
confusion!?
-       {
+    
+    // TODO: Remove this and want_redraw to avoid confusion!?
+       if (redraw_flag)  {
                changed_ranges.setWorld();
        }
        

=== modified file 'libbase/snappingrange.h'
--- a/libbase/snappingrange.h   2009-02-25 22:33:03 +0000
+++ b/libbase/snappingrange.h   2009-04-03 18:13:27 +0000
@@ -8,21 +8,25 @@
 // 
 // This program is distributed in the hope that it will be useful,
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.    See the
 // GNU General Public License for more details.
 // 
 // You should have received a copy of the GNU General Public License
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
 // 
 
 #ifndef GNASH_SNAPPINGRANGE_H
 #define GNASH_SNAPPINGRANGE_H
 
+#include "Range2d.h"
+
 #include <list>
 #include <vector>
-#include "Range2d.h"
+#include <boost/bind.hpp>
+#include <iterator>
+#include <algorithm>
+#include <iostream>
 
 namespace gnash {
 
@@ -48,606 +52,608 @@
 /// The factor method makes sure that very close, but also very different 
 /// shapes, don't get merged, like in the following example:
 ///
-///          +---+
-///          |   |    
-///          |   |    
-///          |   |    
-///          |   |    
-///          |   |
-///          +---+
-///   +-----------------------------------+
-///   |                                   |
-///   +-----------------------------------+    
+///                    +---+
+///                    |   |        
+///                    |   |        
+///                    |   |        
+///                    |   |        
+///                    |   |
+///                    +---+
+///     +-----------------------------------+
+///     |                                   |
+///     +-----------------------------------+        
 ///
 /// Merging these two ranges would create a much bigger range which in some
 /// situations means that rendering is notably slower (for example, when 
 /// there is a scaled bitmap behind these shapes).
-///
+
+// Forward declarations.
+namespace {
+
+    /// returns true when two ranges should be merged together
+    template<typename T> inline bool snaptest(
+            const geometry::Range2d<T>& range1,
+            const geometry::Range2d<T>& range2, const float snapFactor);
+}
 
 template <typename T>
 class SnappingRanges2d
 {
 public:
-  typedef geometry::Range2d<T> RangeType;
-  typedef std::vector<RangeType> RangeList; // TODO: list might be more 
appropriate
-  typedef typename RangeList::size_type size_type;  
-
-  template <typename U>
-  friend std::ostream& operator<< (std::ostream& os, const 
SnappingRanges2d<U>& r);
-  
-  SnappingRanges2d() 
-    :
-    snap_factor(1.3f),
-    single_mode(false),
-    ranges_limit(50),
-    _combine_counter(0)
-  {
-  }
-
-  /// Templated copy constructor, for casting between range types
-  template <typename U>
-  SnappingRanges2d(const SnappingRanges2d<U>& from)
-    :
-    snap_factor(from.getSnapFactor()), 
-    single_mode(from.getSingleMode()),
-    ranges_limit(from.getRangeCountLimit()),
-    _combine_counter(0)
-  {
-    if ( from.isWorld() ) {
-      setWorld();
-    } else if ( from.isNull() ) {
-      setNull();
-    } else {
-      // TODO: can we safely assume that the 'from' parameter was
-      //       finalized ?
-      // from.finalize(); // can't call finalize, it's private !!
-
-      // TODO: use visitor pattern !
-      unsigned rcount = from.size();
-      for (unsigned int rno=0; rno<rcount; rno++)
-      {
-        Range2d<U> r = from.getRange(rno);
-        RangeType rc(r);
-        add(rc);
-      }
-    }
-  }
-  
-  /// Sets the snapping factor (which must be > 1.0). Higher factors make
-  /// the ranges more attractive for snapping. A good value is usually 1.3.
-  void setSnapFactor(float factor) {
-    assert(factor > 1.0f);
-    snap_factor = factor;
-  }
-  
-  float getSnapFactor() const {
-    return snap_factor;
-  }
-  
-  /// if mode==true, then the snapping ranges will act like a normal Range2d
-  void setSingleMode(bool mode) {
-    single_mode = mode;
-  }
-  
-  bool getSingleMode() const {
-    return single_mode;
-  }  
-  
-  /// Sets the maximum number of ranges allowed (to avoid lots of small
-  /// ranges)
-  void setRangeCountLimit(unsigned limit) {
-    ranges_limit = limit;
-  }
-  
-  unsigned getRangeCountLimit() const {
-    return ranges_limit;
-  }
-  
-  /// Copy the snapping settings from another ranges list, without
-  /// copying the ranges itself
-  void inheritConfig(const SnappingRanges2d<T>& from) {
-   snap_factor = from.snap_factor;
-   single_mode = from.single_mode;
-  }
-  
-  /// Add a Range to the set, merging when possible and appropriate
-  void add(const RangeType& range) {
-    if (range.isWorld()) {
-      setWorld();
-      return;
-    }
-    
-    if (range.isNull()) return;
-    
-    if (single_mode) {
-    
-      // single range mode
-    
-      if (_ranges.empty()) {
-        RangeType temp;
-        _ranges.push_back(temp);
-      }
-      
-      _ranges[0].expandTo(range);
-    
-    } else {  
-    
-      // multi range mode
-    
-      for (unsigned int rno=0; rno<_ranges.size(); rno++) {
-        if (snaptest(_ranges[rno], range)) {
-          _ranges[rno].expandTo(range);
-          return;
-        }
-      }
-      
-      // reached this point we need a new range 
-      _ranges.push_back(range);
-      
-      combine_ranges_lazy();
-    }
-  }
-  
-  
-  /// combines two snapping ranges
-  void add(SnappingRanges2d<T> other_ranges) {
-    for (unsigned int rno=0; rno<other_ranges.size(); rno++)
-      add(other_ranges.getRange(rno));
-  }
-  
-  /// Grows all ranges by the specified amount 
-  void growBy(T amount) {
-  
-    if (isWorld() || isNull()) 
-      return;
-    
-    unsigned rcount = _ranges.size();
-    
-    for (unsigned int rno=0; rno<rcount; rno++)
-      _ranges[rno].growBy(amount);
-      
-    combine_ranges_lazy();
-  }
-
-  /// Scale all ranges by the specified factor
-  void scale(float factor) {
-  
-    if (isWorld() || isNull()) 
-      return;
-    
-    unsigned rcount = _ranges.size();
-    
-    for (unsigned int rno=0; rno<rcount; rno++)
-      _ranges[rno].scale(factor);
-      
-    combine_ranges_lazy();
-  }
-  
-  /// Combines known ranges. Previously merged ranges may have come close
-  /// to other ranges. Algorithm could be optimized. 
-  void combine_ranges() {
-  
-    if (single_mode)  // makes no sense in single mode
-      return;
-  
-    bool restart=true;
-    
-    _combine_counter=0;
-    
-    while (restart) {
-    
-      int rcount = _ranges.size();
-
-      restart=false;
-    
-      for (int i=0; i<rcount; i++) {
-      
-        for (int j=i+1; j<rcount; j++) {
-        
-          if (snaptest(_ranges[i], _ranges[j])) {
-            // merge i + j
-            _ranges[i].expandTo(_ranges[j]);
-            
-            _ranges.erase(_ranges.begin() + j);
-            
-            restart=true; // restart from beginning
-            break;
-            
-          } //if
-        
-        } //for
-        
-        if (restart)
-          break;
-      
-      } //for
-    
-    } //while
-    
-    
-    // limit number of ranges
-    if (_ranges.size() > ranges_limit) {
-    
-      // We found way too much ranges, so reduce to just one single range.
-      // We could also double the factor and try again, but that probably
-      // won't make much difference, so we avoid the trouble...
-      
-      RangeType single = getFullArea();      
-      _ranges.resize(1);
-      _ranges[0] = single;
-    
-    }
-  
-  }
-  
-  
-  /// Calls combine_ranges() once in a while, but not always. Avoids too many
-  /// combine_ranges() checks, which could slow down everything.
-  void combine_ranges_lazy() {
-    _combine_counter++;
-    if (_combine_counter > 5) 
-      combine_ranges();
-  }
-      
-  /// returns true, when two ranges should be merged together
-  inline bool snaptest(const RangeType& range1, const RangeType& range2) {
-  
+    typedef geometry::Range2d<T> RangeType;
+    typedef std::vector<RangeType> RangeList; 
+    typedef typename RangeList::size_type size_type;    
+
+    template<typename U> friend std::ostream& operator<<(std::ostream& os,
+                    const SnappingRanges2d<U>& r);
+    
+    SnappingRanges2d() 
+        :
+        _snapFactor(1.3f),
+        _singleMode(false),
+        _rangesLimit(50),
+        _combineCounter(0)
+    {
+    }
+
+    /// Templated copy constructor, for casting between range types
+    template <typename U>
+    SnappingRanges2d(const SnappingRanges2d<U>& from)
+        :
+        _snapFactor(from.getSnapFactor()), 
+        _singleMode(from.getSingleMode()),
+        _rangesLimit(from.getRangeCountLimit()),
+        _combineCounter(0)
+    {
+        if (from.isWorld()) setWorld();
+        else if (from.isNull()) setNull();
+        else {
+            // TODO: can we safely assume that the 'from' parameter was
+            //             finalized ?
+
+            // TODO: use visitor pattern !
+            for (size_type i = 0, e = from.size(); i != e; ++i) {
+                const Range2d<U>& r = from.getRange(i);
+                RangeType rc(r);
+                add(rc);
+            }
+        }
+    }
+    
+    /// Sets the snapping factor (which must be > 1.0). Higher factors make
+    /// the ranges more attractive for snapping. A good value is usually 1.3.
+    void setSnapFactor(const float factor) {
+        assert(factor > 1.0f);
+        _snapFactor = factor;
+    }
+    
+    float getSnapFactor() const {
+        return _snapFactor;
+    }
+    
+    /// if mode==true, then the snapping ranges will act like a normal Range2d
+    void setSingleMode(const bool mode) {
+        _singleMode = mode;
+    }
+    
+    bool getSingleMode() const {
+        return _singleMode;
+    }    
+    
+    /// Sets the maximum number of ranges allowed (to avoid lots of small
+    /// ranges)
+    void setRangeCountLimit(const size_type limit) {
+        _rangesLimit = limit;
+    }
+    
+    size_type getRangeCountLimit() const {
+        return _rangesLimit;
+    }
+    
+    /// Copy the snapping settings from another ranges list, without
+    /// copying the ranges itself
+    void inheritConfig(const SnappingRanges2d<T>& from) {
+        _snapFactor = from._snapFactor;
+        _singleMode = from._singleMode;
+    }
+    
+    /// Merge two ranges based on snaptest.
+    struct ExpandToIfSnap
+    {
+    public:
+        ExpandToIfSnap(const RangeType& rt, const float snapFactor)
+            :
+            _rt(rt),
+            _snapFactor(snapFactor)
+        {}
+        
+        bool operator()(RangeType& r) {
+            if (snaptest(r, _rt, _snapFactor)) {
+                r.expandTo(_rt);
+                return false;
+            }
+            return true;
+        }
+    private:
+        const RangeType& _rt;
+        const float _snapFactor;
+    };
+
+    class Scale
+    {
+    public:
+        Scale(const float scale) : _scale(scale) {}
+        void operator()(RangeType& r) {
+            r.scale(_scale);
+        }
+    private:
+        const float _scale;
+    };
+
+    class GrowBy
+    {
+    public:
+        GrowBy(const float factor) : _factor(factor) {}
+        void operator()(RangeType& r) {
+            r.growBy(_factor);
+        }
+    private:
+        const float _factor;
+    };
+
+    class AddTo
+    {
+    public:
+        AddTo(SnappingRanges2d<T>& us) : _this(us) {}
+        void operator()(const RangeType& r) {
+            _this.add(r);
+        }
+    private:
+        SnappingRanges2d<T>& _this;
+    };
+    
+    class IntersectsRange
+    {
+    public:
+        IntersectsRange(const RangeType& range) : _range(range) {}
+        bool operator()(const RangeType& us) {
+            return us.intersects(_range);
+        }
+    private:
+        const RangeType& _range;
+    };
+    
+    class ContainsPoint
+    {
+    public:
+        ContainsPoint(const T x, const T y) : _x(x), _y(y) {}
+        bool operator()(const RangeType& us) {
+            return us.contains(_x, _y);
+        }
+    private:
+        const T _x, _y;
+    };
+    
+    class ContainsRange
+    {
+    public:
+        ContainsRange(const RangeType& range) : _range(range) {}
+        bool operator()(const RangeType& us) {
+            return us.contains(_range);
+        }
+    private:
+        const RangeType& _range;
+    };
+
+
+    /// Add a Range to the set, merging when possible and appropriate
+    void add(const RangeType& range) {
+        if (range.isWorld()) {
+            setWorld();
+            return;
+        }
+        
+        if (range.isNull()) return;
+        
+        if (_singleMode) {
+            if (_ranges.empty()) _ranges.resize(1);
+            _ranges[0].expandTo(range);
+            return;
+        }
+        
+        ExpandToIfSnap exp(range, _snapFactor);
+        if (visit(exp)) return;
+
+        // reached this point we need a new range 
+        _ranges.push_back(range);
+        
+        combineRangesLazy();
+    }
+    
+    /// combines two snapping ranges
+    void add(const SnappingRanges2d<T>& other) {
+        const RangeList& rl = other._ranges;
+        std::for_each(rl.begin(), rl.end(), AddTo(*this));
+    }
+
+    /// Grows all ranges by the specified amount 
+    void growBy(const T amount) {
+    
+        if (isWorld() || isNull()) return;
+        
+        std::for_each(_ranges.begin(), _ranges.end(), GrowBy(amount));
+        combineRangesLazy();
+    }
+
+    /// Scale all ranges by the specified factor
+    void scale(const float factor) {
+    
+        if (isWorld() || isNull()) return;
+        
+        std::for_each(_ranges.begin(), _ranges.end(), Scale(factor));
+        combineRangesLazy();
+    }
+    
+    /// Resets to NULL range
+    void setNull() {
+        _ranges.clear();
+    }
+    
+    /// Resets to one range with world flags
+    void setWorld() {
+        if (isWorld()) return;
+        _ranges.resize(1);
+        _ranges[0].setWorld();
+    }
+    
+    /// Returns true, when the ranges equal world range
+    bool isWorld() const {
+        return ((size()==1) && (_ranges.front().isWorld()));
+    }
+    
+    /// Returns true, when there is no range
+    bool isNull() const {
+        return _ranges.empty();
+    }
+    
+    /// Returns the number of ranges in the list
+    size_type size() const {
+        finalize();
+        return _ranges.size();
+    }
+    
+    /// Returns the range at the specified index
+    const RangeType& getRange(size_type index) const {
+        finalize();
+        assert(index<size());
+        return _ranges[index];
+    }
+    
+    /// Return a range that surrounds *all* added ranges. This is used mainly
+    /// for compatibilty issues. 
+    RangeType getFullArea() const {
+        RangeType range;
+        
+        range.setNull();
+        
+        int rcount = _ranges.size();
+        
+        for (int rno=0; rno<rcount; rno++) 
+            range.expandTo(_ranges[rno]);
+        
+        return range;     
+    }
+    
+
+    /// Returns true if any of the ranges intersect the given range
+    //
+    /// Note that a NULL range doesn't intersect anything
+    /// and a WORLD range intersects everything except a NULL Range.
+    ///
+    bool intersects(const RangeType& r) const {
+    
+        finalize();
+        return std::find_if(_ranges.begin(), _ranges.end(), IntersectsRange(r))
+            != _ranges.end();
+    }
+    
+    /// Returns true if any of the ranges contains the point
+    bool contains(T x, T y) const {
+    
+        finalize();
+        return std::find_if(_ranges.begin(), _ranges.end(), ContainsPoint(x, 
y))
+            != _ranges.end();
+    }
+
+    /// Returns true if any of the ranges contains the range
+    //
+    /// Note that a NULL range is not contained in any range and
+    /// a WORLD range is onluy contained in another WORLD range.
+    ///
+    bool contains(const RangeType& r) const {
+    
+        finalize();
+        return std::find_if(_ranges.begin(), _ranges.end(), ContainsRange(r))
+            != _ranges.end();
+    }
+
+    /// \brief
+    /// Returns true if all ranges in the given SnappingRanges2d 
+    /// are contained in at least one of the ranges composing this
+    /// one.
+    ///
+    /// Note that a NULL range is not contained in any range and
+    /// a WORLD range is onluy contained in another WORLD range.
+    ///
+    bool contains(const SnappingRanges2d<T>& o) const
+    {
+    
+        finalize();
+        // o.finalize(); // should I finalize the other range too ?
+
+        // Null range set doesn't contain and isn't contained by anything
+        if ( isNull() ) return false;
+        if ( o.isNull() ) return false;
+
+        // World range contains everything (except null ranges)
+        if ( isWorld() ) return true;
+
+        // This snappingrange is neither NULL nor WORLD
+        // The other can still be WORLD, but in that case the
+        // first iteration would return false
+        //
+        /// TODO: use a visitor !
+        for (unsigned rno=0, rcount=o.size(); rno<rcount; rno++) 
+        {
+            RangeType r = o.getRange(rno);
+            if ( ! contains(r) )
+            {
+                return false;
+            }
+        }
+            
+        return true;
+    
+    }
+    
+    
+    /// Intersect this ranges list with the given ranges list,
+    /// updating the current ranges list.
+    /// Note this is currently a relatively expensive operation    
+    /// for complex lists.
+    ///
+    void intersect(const SnappingRanges2d<T>& o) 
+    {
+        if (o.isNull()) {
+            setNull();
+            return;
+        }
+        
+        if (o.isWorld()) return;
+        
+        // We create a new ranges set for each range in "o" and
+        // then update ourselves with the *union* of these ranges.
+        // Anybody knows a better method (in terms of efficieny) ?    
+     
+        std::vector<SnappingRanges2d<T> > list;
+        list.reserve(o.size());
+    
+        //TODO: use a visitor !
+        for (unsigned rno=0, rcount=o.size(); rno<rcount; rno++) {
+            
+            // add a copy of ourselves to the list
+            list.push_back(*this);
+            
+            // intersect that copy with the single range
+            list.back().intersect(o.getRange(rno));
+            
+        } 
+        
+        // update ourselves with the union of the "list"
+        setNull();
+        for (size_type lno=0, lcount=list.size(); lno<lcount; lno++) {
+            add(list[lno]);
+        }
+                            
+    }
+    
+    
+    /// Intersects this ranges list with the given single range,
+    /// updating the current ranges list.
+    void intersect(const RangeType& r) 
+    {
+    
+        finalize();
+
+        if (isWorld()) {            // world intersection with X = X
+            setNull();    
+            add(r);
+            return;
+        }
+        
+        if (isNull()) return; // NULL will always remain NULL
+        
+        if (r.isNull()) {         // X intersection with NULL = NULL
+            setNull();
+            return;
+        }
+        
+        if (r.isWorld()) return;    // X intersection with WORLD = X
+        
+        // TODO: use a vector (remember to walk in reverse dir.)
+        for (int rno=_ranges.size()-1; rno>=0; rno--) {     
+        
+            RangeType newrange = Intersection(_ranges[rno], r);
+            
+            if (newrange.isNull())
+                _ranges.erase(_ranges.begin() + rno);
+            else             
+                _ranges[rno] = newrange;
+        }
+    }
+    
+    /// Combines known ranges. Previously merged ranges may have come close
+    /// to other ranges. Algorithm could be optimized. 
+    void combineRanges() const {
+    
+        // makes no sense in single mode
+        if (_singleMode) return;
+    
+        bool restart = true;
+        
+        _combineCounter = 0;
+        
+        while (restart) {
+        
+            int rcount = _ranges.size();
+
+            restart=false;
+        
+            for (int i=0; i<rcount; i++) {
+            
+                for (int j=i+1; j<rcount; j++) {
+                
+                    if (snaptest(_ranges[i], _ranges[j], _snapFactor)) {
+                        // merge i + j
+                        _ranges[i].expandTo(_ranges[j]);
+                        
+                        _ranges.erase(_ranges.begin() + j);
+                        
+                        restart=true; // restart from beginning
+                        break;
+                        
+                    } 
+                } 
+                
+                if (restart) break;
+            } 
+        } 
+        
+        // limit number of ranges
+        if (_ranges.size() > _rangesLimit) {
+        
+            // We found way too much ranges, so reduce to just one single 
range.
+            // We could also double the factor and try again, but that probably
+            // won't make much difference, so we avoid the trouble...
+            
+            RangeType single = getFullArea();            
+            _ranges.resize(1);
+            _ranges[0] = single;
+        
+        }
+    
+    }
+    
+    /// Visit the current Ranges set
+    //
+    /// Visitor functor will be invoked
+    /// for each RangeType in the current set.
+    /// 
+    /// The visitor functor will 
+    /// receive a RangeType reference; must return true if
+    /// it wants next item or true to exit the loop.
+    ///
+    /// @return false if the visitor reached the end.
+    template<class V> inline bool visit(V& visitor) const
+    {
+        typename RangeList::iterator it, e;
+        for (it = _ranges.begin(), e = _ranges.end(); it != e; ++it) {
+            if (!visitor(*it)) break;
+        }
+        return it != _ranges.end();
+    }
+
+    /// Visit the current Ranges set
+    //
+    /// Visitor functor will be invoked inconditionally
+    /// for each RangeType in the current set.
+    /// 
+    /// The visitor functor will receive a RangeType reference.
+    ///
+    template<class V> inline void visitAll(V& visitor) const
+    {
+        for_each(_ranges.begin(), _ranges.end(), visitor);
+    }
+    
+private:
+
+    
+    /// Calls combineRanges() once in a while, but not always. Avoids too many
+    /// combineRanges() checks, which could slow down everything.
+    void combineRangesLazy() {
+        const size_type max = 5;
+        ++_combineCounter;
+        if (_combineCounter > max) combineRanges();
+    }
+            
+    void finalize() const {
+        if (_combineCounter > 0) combineRanges();
+    } 
+        
+    /// The current Ranges list.
+    //
+    /// Mutable due to lazy finalization. This isn't very nice, but better than
+    /// const_cast.
+    mutable RangeList _ranges;
+
+    /// snapping factor - see setSnapFactor() 
+    float _snapFactor;
+    
+    /// if set, only a single, outer range is maintained (extended). 
+    bool _singleMode;
+    
+    /// maximum number of ranges allowed
+    size_type _rangesLimit;     
+    
+    /// Counter used in finalizing ranges.
+    mutable size_type _combineCounter;
+        
+};
+
+template <class T>
+std::ostream&
+operator<< (std::ostream& os, const SnappingRanges2d<T>& r)
+{
+    if ( r.isNull() ) return os << "NULL";
+    if ( r.isWorld() ) return os << "WORLD";
+
+    typedef typename SnappingRanges2d<T>::RangeList R;
+
+    const R& ranges = r._ranges;
+
+    std::copy(ranges.begin(), ranges.end(),
+            std::ostream_iterator<typename R::value_type>(os, ","));
+
+    return os;
+}
+    
+namespace {
+
+template<typename T>
+inline bool snaptest(const geometry::Range2d<T>& range1,
+        const geometry::Range2d<T>& range2, const float snapFactor)
+{
+
     // when they intersect anyway, they should of course be merged! 
     // TODO: not really, a "+" style ranges list might be worth to 
     // remain unmerged (but needs special handling, i.e. create three
     // ranges out of two)...
-    if (range1.intersects(range2)) 
-      return true;
-      
-    // simply search for the minimum x or y distances
-    /*
-  
-    T xdist = 99999999;
-    T ydist = 99999999;
-    T xa1 = range1.getMinX();
-    T xa2 = range2.getMinX();
-    T xb1 = range1.getMaxX();
-    T xb2 = range2.getMaxX();
-    T ya1 = range1.getMinY();
-    T ya2 = range2.getMinY();
-    T yb1 = range1.getMaxY();
-    T yb2 = range2.getMaxY();
-    
-    xdist = absmin(xdist, xa1-xa2);
-    xdist = absmin(xdist, xa1-xb2);
-    xdist = absmin(xdist, xb1-xa2);
-    xdist = absmin(xdist, xb1-xb2);
-
-    ydist = absmin(ydist, ya1-ya2);
-    ydist = absmin(ydist, ya1-yb2);
-    ydist = absmin(ydist, yb1-ya2);
-    ydist = absmin(ydist, yb1-yb2);
-    
-    return (xdist + ydist) <= snap_distance;
-    */
-    
-    RangeType temp = range1;
+    if (range1.intersects(range2)) return true;
+        
+    geometry::Range2d<T> temp = range1;
     temp.expandTo(range2);
     
-    return (range1.getArea() + range2.getArea()) * snap_factor > 
temp.getArea();
-
-  } 
-    
-  /// Resets to NULL range
-  void setNull() {
-    _ranges.clear();
-  }
-  
-  /// Resets to one range with world flags
-  void setWorld() {
-    if (isWorld()) return;
-    _ranges.resize(1);
-    _ranges[0].setWorld();
-  }
-  
-  /// Returns true, when the ranges equal world range
-  bool isWorld() const {
-    return ( (size()==1) && (_ranges.front().isWorld()) );
-  }
-  
-  /// Returns true, when there is no range
-  bool isNull() const {
-    return _ranges.empty();
-  }
-  
-  /// Returns the number of ranges in the list
-  size_type size() const {
-    finalize();
-    return _ranges.size();
-  }
-  
-  /// Returns the range at the specified index
-  //
-  /// TODO: return by reference ?
-  ///
-  RangeType getRange(unsigned int index) const {
-    finalize();
-    assert(index<size());
-    
-    return _ranges[index];
-  }
-  
-  /// Return a range that surrounds *all* added ranges. This is used mainly
-  /// for compatibilty issues. 
-  RangeType getFullArea() const {
-    RangeType range;
-    
-    range.setNull();
-    
-    int rcount = _ranges.size();
-    
-    for (int rno=0; rno<rcount; rno++) 
-      range.expandTo(_ranges[rno]);
-    
-    return range;   
-  }
-  
-  
-  /// Returns true if any of the ranges contains the point
-  bool contains(T x, T y) const {
-  
-    finalize();
-  
-    for (unsigned rno=0, rcount=_ranges.size(); rno<rcount; rno++) 
-    if (_ranges[rno].contains(x,y))
-      return true;
-      
-    return false;
-  
-  }
-
-  /// Returns true if any of the ranges contains the range
-  //
-  /// Note that a NULL range is not contained in any range and
-  /// a WORLD range is onluy contained in another WORLD range.
-  ///
-  bool contains(const RangeType& r) const {
-  
-    finalize();
-  
-    for (unsigned rno=0, rcount=_ranges.size(); rno<rcount; rno++) 
-    if (_ranges[rno].contains(r))
-      return true;
-      
-    return false;
-  
-  }
-
-  /// Returns true if any of the ranges intersect the given range
-  //
-  /// Note that a NULL range doesn't intersect anything
-  /// and a WORLD range intersects everything except a NULL Range.
-  ///
-  bool intersects(const RangeType& r) const {
-  
-    finalize();
-  
-    for (unsigned rno=0, rcount=_ranges.size(); rno<rcount; rno++) 
-    if (_ranges[rno].intersects(r))
-      return true;
-      
-    return false;
-  
-  }
-
-  /// \brief
-  /// Returns true if all ranges in the given SnappingRanges2d 
-  /// are contained in at least one of the ranges composing this
-  /// one.
-  ///
-  /// Note that a NULL range is not contained in any range and
-  /// a WORLD range is onluy contained in another WORLD range.
-  ///
-  bool contains(const SnappingRanges2d<T>& o) const
-  {
-  
-    finalize();
-    // o.finalize(); // should I finalize the other range too ?
-
-    // Null range set doesn't contain and isn't contained by anything
-    if ( isNull() ) return false;
-    if ( o.isNull() ) return false;
-
-    // World range contains everything (except null ranges)
-    if ( isWorld() ) return true;
-
-    // This snappingrange is neither NULL nor WORLD
-    // The other can still be WORLD, but in that case the
-    // first iteration would return false
-    //
-    /// TODO: use a visitor !
-    ///
-    for (unsigned rno=0, rcount=o.size(); rno<rcount; rno++) 
-    {
-      RangeType r = o.getRange(rno);
-      if ( ! contains(r) )
-      {
-        return false;
-      }
-    }
-      
-    return true;
-  
-  }
-  
-  
-  /// Intersect this ranges list with the given ranges list,
-  /// updating the current ranges list.
-  /// Note this is currently a relatively expensive operation  
-  /// for complex lists.
-  ///
-  void intersect(const SnappingRanges2d<T>& o) 
-  {
-    if (o.isNull()) {
-      setNull();
-      return;
-    }
-    
-    if (o.isWorld()) return;
-    
-    // We create a new ranges set for each range in "o" and
-    // then update ourselves with the *union* of these ranges.
-    // Anybody knows a better method (in terms of efficieny) ?  
-   
-    std::vector< SnappingRanges2d<T> > list;
-  
-    //TODO: use a visitor !
-    for (unsigned rno=0, rcount=o.size(); rno<rcount; rno++) {
-      
-      // add a copy of ourselves to the list
-      list.push_back(*this);
-      
-      // intersect that copy with the single range
-      list.back().intersect(o.getRange(rno));
-      
-    } 
-    
-    // update ourselves with the union of the "list"
-    setNull();
-    for (unsigned lno=0, lcount=list.size(); lno<lcount; lno++) 
-      add(list.at(lno));
-              
-  }
-  
-  
-  /// Intersects this ranges list with the given single range,
-  /// updating the current ranges list.
-  void intersect(const RangeType& r) 
-  {
-  
-    finalize();
-
-    if (isWorld()) {      // world intersection with X = X
-      setNull();  
-      add(r);
-      return;
-    }
-    
-    if (isNull()) return; // NULL will always remain NULL
-    
-    if (r.isNull()) {     // X intersection with NULL = NULL
-      setNull();
-      return;
-    }
-    
-    if (r.isWorld()) return;  // X intersection with WORLD = X
-    
-    
-    // TODO: use a vector (remember to walk in reverse dir.)
-    for (int rno=_ranges.size()-1; rno>=0; rno--) {   
-    
-      RangeType newrange = Intersection(_ranges[rno], r);
-      
-      if (newrange.isNull())
-        _ranges.erase(_ranges.begin() + rno);
-      else       
-        _ranges[rno] = newrange;
-    }
-  }
-  
-  
-  /// Visit the current Ranges set
-  //
-  /// Visitor functor will be invoked
-  /// for each RangeType in the current set.
-  /// 
-  /// The visitor functor will 
-  /// receive a RangeType reference; must return true if
-  /// it wants next item or false to exit the loop.
-  ///
-  template <class V>
-  inline void visit(V& visitor) const
-  {
-    for (typename RangeList::const_iterator
-      it = _ranges.begin(), itEnd = _ranges.end();
-      it != itEnd;
-      ++it)
-    {
-      if ( ! visitor(*it) )
-      {
-        break;
-      }
-    }
-  }
-
-  /// Visit the current Ranges set
-  //
-  /// Visitor functor will be invoked inconditionally
-  /// for each RangeType in the current set.
-  /// 
-  /// The visitor functor will receive a RangeType reference.
-  ///
-  template <class V>
-  inline void visitAll(V& visitor) const
-  {
-    for (typename RangeList::const_iterator
-      it = _ranges.begin(), itEnd = _ranges.end();
-      it != itEnd;
-      ++it)
-    {
-      visitor(*it);
-    }
-  }
-  
-private:
-
-  // Unused...
-  inline T absmin(T a, T b) {
-    if (b<0) b*=-1;
-    return std::min<T>(a,b);
-  }
-  
-  void finalize() const {
-    if (_combine_counter > 0) {
-      SnappingRanges2d<T>* me_nonconst = const_cast< SnappingRanges2d<T>* > 
(this); 
-      me_nonconst->combine_ranges();
-    }
-  } 
-  
-    
-  // The current Ranges list
-  RangeList _ranges;
-
-  /// snapping factor - see setSnapFactor() 
-  float snap_factor;
-  
-  /// if set, only a single, outer range is maintained (extended). 
-  bool single_mode;
-  
-  /// maximum number of ranges allowed
-  unsigned ranges_limit;   
-  
-  unsigned int _combine_counter;
-    
-}; //class SnappingRanges2d
-
-template <class T>
-std::ostream& operator<< (std::ostream& os, const SnappingRanges2d<T>& r)
-{
-  if ( r.isNull() ) return os << "NULL";
-  if ( r.isWorld() ) return os << "WORLD";
-
-  for (typename SnappingRanges2d<T>::RangeList::const_iterator
-    it = r._ranges.begin(), itEnd = r._ranges.end();
-    it != itEnd; ++it)
-  {
-    if ( it != r._ranges.begin() ) os << ", ";
-    os << *it;
-  }
-  return os;
-}
-
-} //namespace gnash.geometry
-
-/// Standard snapping 2d ranges type for invalidated bounds calculation  
+    return (range1.getArea() + range2.getArea()) * snapFactor >
+        temp.getArea();
+
+} 
+    
+} // anonymous namespace
+} // namespace geometry
+
+/// Standard snapping 2d ranges type for invalidated bounds calculation    
 typedef geometry::SnappingRanges2d<float> InvalidatedRanges;
 
-
 } //namespace gnash
 
 #endif

=== modified file 'libcore/movie_root.h'
--- a/libcore/movie_root.h      2009-04-03 12:05:21 +0000
+++ b/libcore/movie_root.h      2009-04-03 18:45:30 +0000
@@ -775,6 +775,12 @@
     DSOEXPORT std::string callInterface(const std::string& cmd,
             const std::string& arg = std::string()) const;
 
+    /// Send an error message to the hosting application.
+    //
+    /// @param msg  A message to send describing the error.
+    //
+    /// The hosting app decides what to do with the message, or whether it
+    /// wants to do anything at all. It may show a popup box.
     DSOEXPORT void errorInterface(const std::string& msg) const;
 
     /// Called from the ScriptLimits tag parser to set the


reply via email to

[Prev in Thread] Current Thread [Next in Thread]