[Top][All Lists]
[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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Gnash-commit] /srv/bzr/gnash/trunk r10765: Document movie_root::errorInterface(). Tidy up snappingrange a bit.,
Benjamin Wolsey <=