summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKrzysztof Kosi??ski <tweenk.pl@gmail.com>2011-08-25 19:16:02 +0000
committerKrzysztof Kosinski <tweenk.pl@gmail.com>2011-08-25 19:16:02 +0000
commit093f4174abc07b4ea523617fccdd8028f2670fea (patch)
tree5aba6cd030bc6b0dbb59ec48e32a0b0364b516bd
parentGerman translation update (diff)
parentReduce default rendering cache size to 64 MiB (diff)
downloadinkscape-093f4174abc07b4ea523617fccdd8028f2670fea.tar.gz
inkscape-093f4174abc07b4ea523617fccdd8028f2670fea.zip
Merge rendering cache branch (GSoC 2011)
(bzr r10579)
-rw-r--r--src/2geom/affine.cpp12
-rw-r--r--src/2geom/affine.h10
-rw-r--r--src/2geom/coord.h38
-rw-r--r--src/2geom/generic-interval.h8
-rw-r--r--src/2geom/generic-rect.h105
-rw-r--r--src/2geom/interval.h3
-rw-r--r--src/2geom/linear.h2
-rw-r--r--src/2geom/rect.h1
-rw-r--r--src/2geom/transforms.h30
-rw-r--r--src/context-fns.h1
-rw-r--r--src/desktop.cpp102
-rw-r--r--src/desktop.h12
-rw-r--r--src/dialogs/clonetiler.cpp56
-rw-r--r--src/display/Makefile_insert28
-rw-r--r--src/display/cairo-templates.h4
-rw-r--r--src/display/canvas-arena.cpp302
-rw-r--r--src/display/canvas-arena.h23
-rw-r--r--src/display/display-forward.h18
-rw-r--r--src/display/drawing-context.cpp152
-rw-r--r--src/display/drawing-context.h128
-rw-r--r--src/display/drawing-group.cpp165
-rw-r--r--src/display/drawing-group.h62
-rw-r--r--src/display/drawing-image.cpp264
-rw-r--r--src/display/drawing-image.h67
-rw-r--r--src/display/drawing-item.cpp900
-rw-r--r--src/display/drawing-item.h212
-rw-r--r--src/display/drawing-shape.cpp343
-rw-r--r--src/display/drawing-shape.h63
-rw-r--r--src/display/drawing-surface.cpp354
-rw-r--r--src/display/drawing-surface.h93
-rw-r--r--src/display/drawing-text.cpp255
-rw-r--r--src/display/drawing-text.h83
-rw-r--r--src/display/drawing.cpp205
-rw-r--r--src/display/drawing.h113
-rw-r--r--src/display/grayscale.cpp2
-rw-r--r--src/display/nr-arena-forward.h51
-rw-r--r--src/display/nr-arena-glyphs.cpp476
-rw-r--r--src/display/nr-arena-glyphs.h108
-rw-r--r--src/display/nr-arena-group.cpp299
-rw-r--r--src/display/nr-arena-group.h61
-rw-r--r--src/display/nr-arena-image.cpp408
-rw-r--r--src/display/nr-arena-image.h66
-rw-r--r--src/display/nr-arena-item.cpp882
-rw-r--r--src/display/nr-arena-item.h200
-rw-r--r--src/display/nr-arena-shape.cpp610
-rw-r--r--src/display/nr-arena-shape.h81
-rw-r--r--src/display/nr-arena.cpp185
-rw-r--r--src/display/nr-arena.h69
-rw-r--r--src/display/nr-filter-blend.cpp16
-rw-r--r--src/display/nr-filter-blend.h2
-rw-r--r--src/display/nr-filter-colormatrix.cpp5
-rw-r--r--src/display/nr-filter-colormatrix.h1
-rw-r--r--src/display/nr-filter-component-transfer.cpp5
-rw-r--r--src/display/nr-filter-component-transfer.h1
-rw-r--r--src/display/nr-filter-composite.cpp5
-rw-r--r--src/display/nr-filter-composite.h1
-rw-r--r--src/display/nr-filter-convolve-matrix.cpp5
-rw-r--r--src/display/nr-filter-convolve-matrix.h1
-rw-r--r--src/display/nr-filter-diffuselighting.cpp6
-rw-r--r--src/display/nr-filter-diffuselighting.h1
-rw-r--r--src/display/nr-filter-displacement-map.cpp5
-rw-r--r--src/display/nr-filter-displacement-map.h6
-rw-r--r--src/display/nr-filter-flood.cpp7
-rw-r--r--src/display/nr-filter-flood.h6
-rw-r--r--src/display/nr-filter-gaussian.cpp18
-rw-r--r--src/display/nr-filter-gaussian.h1
-rw-r--r--src/display/nr-filter-image.cpp52
-rw-r--r--src/display/nr-filter-image.h2
-rw-r--r--src/display/nr-filter-merge.cpp16
-rw-r--r--src/display/nr-filter-merge.h2
-rw-r--r--src/display/nr-filter-morphology.cpp7
-rw-r--r--src/display/nr-filter-morphology.h2
-rw-r--r--src/display/nr-filter-offset.cpp5
-rw-r--r--src/display/nr-filter-offset.h1
-rw-r--r--src/display/nr-filter-primitive.cpp4
-rw-r--r--src/display/nr-filter-primitive.h41
-rw-r--r--src/display/nr-filter-slot.cpp62
-rw-r--r--src/display/nr-filter-slot.h17
-rw-r--r--src/display/nr-filter-specularlighting.cpp135
-rw-r--r--src/display/nr-filter-specularlighting.h2
-rw-r--r--src/display/nr-filter-tile.cpp5
-rw-r--r--src/display/nr-filter-tile.h1
-rw-r--r--src/display/nr-filter-turbulence.cpp5
-rw-r--r--src/display/nr-filter-turbulence.h2
-rw-r--r--src/display/nr-filter-units.cpp4
-rw-r--r--src/display/nr-filter.cpp137
-rw-r--r--src/display/nr-filter.h21
-rw-r--r--src/display/nr-style.cpp40
-rw-r--r--src/display/nr-style.h13
-rw-r--r--src/display/rendermode.h8
-rw-r--r--src/display/sp-canvas-item.h2
-rw-r--r--src/display/sp-canvas.cpp27
-rw-r--r--src/document.cpp14
-rw-r--r--src/ege-adjustment-action.cpp9
-rw-r--r--src/ege-select-one-action.cpp15
-rw-r--r--src/extension/internal/cairo-png-out.cpp11
-rw-r--r--src/extension/internal/cairo-ps-out.cpp10
-rw-r--r--src/extension/internal/cairo-render-context.cpp15
-rw-r--r--src/extension/internal/cairo-renderer-pdf-out.cpp11
-rw-r--r--src/extension/internal/cairo-renderer.cpp8
-rw-r--r--src/extension/internal/emf-win32-inout.cpp13
-rw-r--r--src/extension/internal/latex-pstricks-out.cpp16
-rw-r--r--src/extension/print.cpp23
-rw-r--r--src/extension/print.h10
-rw-r--r--src/flood-context.cpp146
-rw-r--r--src/helper/Makefile_insert1
-rw-r--r--src/helper/pixbuf-ops.cpp75
-rw-r--r--src/helper/png-write.cpp51
-rw-r--r--src/interface.cpp8
-rw-r--r--src/libnrtype/Layout-TNG-Output.cpp17
-rw-r--r--src/libnrtype/Layout-TNG.h5
-rw-r--r--src/marker.cpp42
-rw-r--r--src/marker.h2
-rw-r--r--src/preferences-skeleton.h1
-rw-r--r--src/print.cpp26
-rw-r--r--src/print.h1
-rw-r--r--src/select-context.cpp18
-rw-r--r--src/sp-clippath.cpp39
-rw-r--r--src/sp-clippath.h4
-rw-r--r--src/sp-flowtext.cpp41
-rw-r--r--src/sp-flowtext.h6
-rw-r--r--src/sp-image.cpp29
-rw-r--r--src/sp-item-group.cpp77
-rw-r--r--src/sp-item-group.h4
-rw-r--r--src/sp-item.cpp162
-rw-r--r--src/sp-item.h15
-rw-r--r--src/sp-mask.cpp36
-rw-r--r--src/sp-mask.h4
-rw-r--r--src/sp-pattern.cpp72
-rw-r--r--src/sp-root.cpp22
-rw-r--r--src/sp-shape.cpp69
-rw-r--r--src/sp-shape.h4
-rw-r--r--src/sp-switch.cpp12
-rw-r--r--src/sp-switch.h2
-rw-r--r--src/sp-symbol.cpp20
-rw-r--r--src/sp-text.cpp47
-rw-r--r--src/sp-text.h4
-rw-r--r--src/sp-tref.cpp1
-rw-r--r--src/sp-use.cpp35
-rw-r--r--src/svg-view.cpp11
-rw-r--r--src/text-context.h1
-rw-r--r--src/trace/trace.cpp59
-rw-r--r--src/ui/cache/svg_preview_cache.cpp61
-rw-r--r--src/ui/cache/svg_preview_cache.h23
-rw-r--r--src/ui/dialog/color-item.cpp18
-rw-r--r--src/ui/dialog/color-item.h3
-rw-r--r--src/ui/dialog/filedialogimpl-win32.cpp4
-rw-r--r--src/ui/dialog/icon-preview.cpp21
-rw-r--r--src/ui/dialog/inkscape-preferences.cpp54
-rw-r--r--src/ui/dialog/inkscape-preferences.h9
-rw-r--r--src/ui/dialog/swatches.cpp24
-rw-r--r--src/ui/view/view.h2
-rw-r--r--src/widgets/desktop-widget.cpp5
-rw-r--r--src/widgets/icon.cpp119
-rw-r--r--src/widgets/stroke-style.cpp15
155 files changed, 4988 insertions, 5111 deletions
diff --git a/src/2geom/affine.cpp b/src/2geom/affine.cpp
index 2a1f18d77..c31b9ba90 100644
--- a/src/2geom/affine.cpp
+++ b/src/2geom/affine.cpp
@@ -410,6 +410,9 @@ Affine &Affine::operator*=(Affine const &o) {
}
//TODO: What's this!?!
+/** Given a matrix m such that unit_circle = m*x, this returns the
+ * quadratic form x*A*x = 1.
+ * @relates Affine */
Affine elliptic_quadratic_form(Affine const &m) {
double od = m[0] * m[1] + m[2] * m[3];
Affine ret (m[0]*m[0] + m[1]*m[1], od,
@@ -469,6 +472,15 @@ Eigen::Eigen(double m[2][2]) {
vectors[i] = Point(0,0);
}
+/** @brief Nearness predicate for affine transforms
+ * @returns True if all entries of matrices are within eps of each other */
+bool are_near(Affine const &a, Affine const &b, Coord eps)
+{
+ return are_near(a[0], b[0], eps) && are_near(a[1], b[1], eps) &&
+ are_near(a[2], b[2], eps) && are_near(a[3], b[3], eps) &&
+ are_near(a[4], b[4], eps) && are_near(a[5], b[5], eps);
+}
+
} //namespace Geom
/*
diff --git a/src/2geom/affine.h b/src/2geom/affine.h
index d7a7a0692..22f8bd9f5 100644
--- a/src/2geom/affine.h
+++ b/src/2geom/affine.h
@@ -200,9 +200,8 @@ inline std::ostream &operator<< (std::ostream &out_file, const Geom::Affine &m)
return out_file;
}
-/** Given a matrix m such that unit_circle = m*x, this returns the
- * quadratic form x*A*x = 1.
- * @relates Affine */
+// Affine factories
+Affine from_basis(const Point x_basis, const Point y_basis, const Point offset=Point(0,0));
Affine elliptic_quadratic_form(Affine const &m);
/** Given a matrix (ignoring the translation) this returns the eigen
@@ -215,9 +214,6 @@ public:
Eigen(double M[2][2]);
};
-// Affine factories
-Affine from_basis(const Point x_basis, const Point y_basis, const Point offset=Point(0,0));
-
/** @brief Create an identity matrix.
* This is a convenience function identical to Affine::identity(). */
inline Affine identity() {
@@ -239,6 +235,8 @@ inline Affine Affine::identity() {
return ret; // allow NRVO
}
+bool are_near(Affine const &a1, Affine const &a2, Coord eps=EPSILON);
+
} // end namespace Geom
#endif // LIB2GEOM_SEEN_AFFINE_H
diff --git a/src/2geom/coord.h b/src/2geom/coord.h
index f7bf2c5d0..90e776665 100644
--- a/src/2geom/coord.h
+++ b/src/2geom/coord.h
@@ -34,6 +34,7 @@
#include <cmath>
#include <limits>
+#include <boost/operators.hpp>
#include <2geom/forward.h>
namespace Geom {
@@ -62,6 +63,9 @@ inline bool rel_error_bound(Coord a, Coord b, double eps=EPSILON) { return a <=
template <typename C>
struct CoordTraits {};
+// NOTE: operator helpers for Rect and Interval are defined here.
+// This is to avoid increasing their size through multiple inheritance.
+
template<>
struct CoordTraits<IntCoord> {
typedef IntPoint PointType;
@@ -69,6 +73,22 @@ struct CoordTraits<IntCoord> {
typedef OptIntInterval OptIntervalType;
typedef IntRect RectType;
typedef OptIntRect OptRectType;
+
+ typedef
+ boost::equality_comparable< IntervalType
+ , boost::additive< IntervalType
+ , boost::additive< IntervalType, IntCoord
+ , boost::orable< IntervalType
+ > > > >
+ IntervalOps;
+
+ typedef
+ boost::equality_comparable< RectType
+ , boost::orable< RectType
+ , boost::orable< RectType, OptRectType
+ , boost::additive< RectType, PointType
+ > > > >
+ RectOps;
};
template<>
@@ -78,6 +98,24 @@ struct CoordTraits<Coord> {
typedef OptInterval OptIntervalType;
typedef Rect RectType;
typedef OptRect OptRectType;
+
+ typedef
+ boost::equality_comparable< IntervalType
+ , boost::additive< IntervalType
+ , boost::multipliable< IntervalType
+ , boost::orable< IntervalType
+ , boost::arithmetic< IntervalType, Coord
+ > > > > >
+ IntervalOps;
+
+ typedef
+ boost::equality_comparable< RectType
+ , boost::orable< RectType
+ , boost::orable< RectType, OptRectType
+ , boost::additive< RectType, PointType
+ , boost::multipliable< RectType, Affine
+ > > > > >
+ RectOps;
};
} // end namespace Geom
diff --git a/src/2geom/generic-interval.h b/src/2geom/generic-interval.h
index a32e97d4b..0212da676 100644
--- a/src/2geom/generic-interval.h
+++ b/src/2geom/generic-interval.h
@@ -34,7 +34,7 @@
#include <cassert>
#include <boost/none.hpp>
#include <boost/optional.hpp>
-#include <boost/operators.hpp>
+#include <2geom/coord.h>
namespace Geom {
@@ -47,11 +47,7 @@ class GenericOptInterval;
*/
template <typename C>
class GenericInterval
- : boost::equality_comparable< GenericInterval<C>
- , boost::additive< GenericInterval<C>
- , boost::additive< GenericInterval<C>, C
- , boost::orable< GenericInterval<C>
- > > > >
+ : CoordTraits<C>::IntervalOps
{
typedef GenericInterval<C> Self;
protected:
diff --git a/src/2geom/generic-rect.h b/src/2geom/generic-rect.h
index 2db30dfa9..efe499809 100644
--- a/src/2geom/generic-rect.h
+++ b/src/2geom/generic-rect.h
@@ -42,6 +42,7 @@
#include <limits>
#include <boost/optional.hpp>
+#include <2geom/coord.h>
namespace Geom {
@@ -54,11 +55,7 @@ class GenericOptRect;
*/
template <typename C>
class GenericRect
- : boost::additive< typename CoordTraits<C>::RectType, typename CoordTraits<C>::PointType
- , boost::equality_comparable< typename CoordTraits<C>::RectType
- , boost::orable< typename CoordTraits<C>::RectType
- , boost::orable< typename CoordTraits<C>::RectType, typename CoordTraits<C>::OptRectType
- > > > >
+ : CoordTraits<C>::RectOps
{
typedef typename CoordTraits<C>::IntervalType CInterval;
typedef typename CoordTraits<C>::PointType CPoint;
@@ -131,15 +128,22 @@ public:
/// @name Inspect dimensions.
/// @{
- CInterval &operator[](unsigned i) { return f[i]; }
+ CInterval &operator[](unsigned i) { return f[i]; }
CInterval const &operator[](unsigned i) const { return f[i]; }
+ CInterval &operator[](Dim2 d) { return f[d]; }
+ CInterval const &operator[](Dim2 d) const { return f[d]; }
+ /** @brief Get the corner of the rectangle with smallest coordinate values.
+ * In 2Geom standard coordinate system, this means upper left. */
CPoint min() const { return CPoint(f[X].min(), f[Y].min()); }
+ /** @brief Get the corner of the rectangle with largest coordinate values.
+ * In 2Geom standard coordinate system, this means lower right. */
CPoint max() const { return CPoint(f[X].max(), f[Y].max()); }
/** @brief Return the n-th corner of the rectangle.
- * If the Y axis grows upwards, this returns corners in clockwise order
- * starting from the lower left. If Y grows downwards, it returns the corners
- * in counter-clockwise order starting from the upper left. */
+ * Returns corners in the direction of growing angles, starting from
+ * the one given by min(). For the standard coordinate system used
+ * in 2Geom (+Y downwards), this means clockwise starting from
+ * the upper left. */
CPoint corner(unsigned i) const {
switch(i % 4) {
case 0: return CPoint(f[X].min(), f[Y].min());
@@ -196,10 +200,10 @@ public:
}
/** @brief Check whether the rectangles have any common points.
- * A non-empty rectangle will not intersect empty rectangles. */
+ * Empty rectangles will not intersect with any other rectangle. */
inline bool intersects(OptCRect const &r) const;
/** @brief Check whether the rectangle includes all points in the given rectangle.
- * A non-empty rectangle will contain any empty rectangle. */
+ * Empty rectangles will be contained in any non-empty rectangle. */
inline bool contains(OptCRect const &r) const;
/** @brief Check whether the given point is within the rectangle. */
@@ -224,11 +228,11 @@ public:
void expandTo(CPoint const &p) {
f[X].expandTo(p[X]); f[Y].expandTo(p[Y]);
}
- /** @brief Enlarge the rectangle to contain the given rectangle. */
+ /** @brief Enlarge the rectangle to contain the argument. */
void unionWith(CRect const &b) {
f[X].unionWith(b[X]); f[Y].unionWith(b[Y]);
}
- /** @brief Enlarge the rectangle to contain the given rectangle.
+ /** @brief Enlarge the rectangle to contain the argument.
* Unioning with an empty rectangle results in no changes. */
void unionWith(OptCRect const &b);
@@ -244,7 +248,8 @@ public:
* This will expand the width by the X coordinate of the point in both directions
* and the height by Y coordinate of the point. Negative coordinate values will
* shrink the rectangle. If <code>-p[X]</code> is larger than half of the width,
- * the X interval will contain only the X coordinate of the midpoint; same for height. */
+ * the X interval will contain only the X coordinate of the midpoint;
+ * same for height. */
void expandBy(CPoint const &p) {
f[X].expandBy(p[X]); f[Y].expandBy(p[Y]);
}
@@ -297,30 +302,66 @@ class GenericOptRect
typedef typename CoordTraits<C>::OptRectType OptCRect;
typedef boost::optional<CRect> Base;
public:
+ /// @name Create potentially empty rectangles.
+ /// @{
GenericOptRect() : Base() {}
GenericOptRect(GenericRect<C> const &a) : Base(CRect(a)) {}
GenericOptRect(CPoint const &a, CPoint const &b) : Base(CRect(a, b)) {}
- /**
- * Creates an empty OptRect when one of the argument intervals is empty.
- */
+ /// Creates an empty OptRect when one of the argument intervals is empty.
GenericOptRect(OptCInterval const &x_int, OptCInterval const &y_int) {
if (x_int && y_int) {
*this = CRect(*x_int, *y_int);
}
// else, stay empty.
}
+ /** @brief Create a rectangle from a range of points.
+ * The resulting rectangle will contain all ponts from the range.
+ * If the range contains no points, the result will be an empty rectangle.
+ * The return type of iterators must be convertible to the corresponding
+ * point type (Point or IntPoint).
+ * @param start Beginning of the range
+ * @param end End of the range
+ * @return Rectangle that contains all points from [start, end). */
+ template <typename InputIterator>
+ static OptCRect from_range(InputIterator start, InputIterator end) {
+ OptCRect result;
+ for (; start != end; ++start) {
+ result.expandTo(*start);
+ }
+ return result;
+ }
+ /// @}
+ /// @name Check other rectangles and points for inclusion.
+ /// @{
/** @brief Check for emptiness. */
inline bool isEmpty() const { return !*this; };
-
+ /** @brief Check whether the rectangles have any common points.
+ * Empty rectangles will not intersect with any other rectangle. */
bool intersects(CRect const &r) const { return r.intersects(*this); }
+ /** @brief Check whether the rectangle includes all points in the given rectangle.
+ * Empty rectangles will be contained in any non-empty rectangle. */
bool contains(CRect const &r) const { return *this && (*this)->contains(r); }
+ /** @brief Check whether the rectangles have any common points.
+ * Empty rectangles will not intersect with any other rectangle.
+ * Two empty rectangles will not intersect each other. */
bool intersects(OptCRect const &r) const { return *this && (*this)->intersects(r); }
+ /** @brief Check whether the rectangle includes all points in the given rectangle.
+ * Empty rectangles will be contained in any non-empty rectangle.
+ * An empty rectangle will not contain other empty rectangles. */
bool contains(OptCRect const &r) const { return *this && (*this)->contains(r); }
+ /** @brief Check whether the given point is within the rectangle.
+ * An empty rectangle will not contain any points. */
bool contains(CPoint const &p) const { return *this && (*this)->contains(p); }
+ /// @}
+ /// @name Modify the potentially empty rectangle.
+ /// @{
+ /** @brief Enlarge the rectangle to contain the argument.
+ * If this rectangle is empty, after callng this method it will
+ * be equal to the argument. */
void unionWith(CRect const &b) {
if (*this) {
(*this)->unionWith(b);
@@ -328,9 +369,16 @@ public:
*this = b;
}
}
+ /** @brief Enlarge the rectangle to contain the argument.
+ * Unioning with an empty rectangle results in no changes.
+ * If this rectangle is empty, after calling this method it will
+ * be equal to the argument. */
void unionWith(OptCRect const &b) {
if (b) unionWith(*b);
}
+ /** @brief Leave only the area overlapping with the argument.
+ * If the rectangles do not have any points in common, after calling
+ * this method the rectangle will be empty. */
void intersectWith(CRect const &b) {
if (!*this) return;
OptCInterval x = (**this)[X] & b[X], y = (**this)[Y] & b[Y];
@@ -340,6 +388,9 @@ public:
*(static_cast<Base*>(this)) = boost::none;
}
}
+ /** @brief Leave only the area overlapping with the argument.
+ * If the argument is empty or the rectangles do not have any points
+ * in common, after calling this method the rectangle will be empty. */
void intersectWith(OptCRect const &b) {
if (b) {
intersectWith(*b);
@@ -347,18 +398,36 @@ public:
*(static_cast<Base*>(this)) = boost::none;
}
}
+ /** @brief Create or enlarge the rectangle to contain the given point.
+ * If the rectangle is empty, after calling this method it will be non-empty
+ * and it will contain only the given point. */
+ void expandTo(CPoint const &p) {
+ if (*this) {
+ (*this).expandTo(p);
+ } else {
+ *this = CRect(p, p);
+ }
+ }
+ /// @}
+
+ /// @name Operators
+ /// @{
+ /** @brief Union with @a b */
GenericOptRect<C> &operator|=(OptCRect const &b) {
unionWith(b);
return *this;
}
+ /** @brief Intersect with @a b */
GenericOptRect<C> &operator&=(CRect const &b) {
intersectWith(b);
return *this;
}
+ /** @brief Intersect with @a b */
GenericOptRect<C> &operator&=(OptCRect const &b) {
intersectWith(b);
return *this;
}
+ /// @}
};
template <typename C>
diff --git a/src/2geom/interval.h b/src/2geom/interval.h
index e95da4811..711eaa5e2 100644
--- a/src/2geom/interval.h
+++ b/src/2geom/interval.h
@@ -63,9 +63,6 @@ typedef GenericOptInterval<Coord> OptInterval;
*/
class Interval
: public GenericInterval<Coord>
- , boost::multipliable< Interval
- , boost::multiplicative< Interval, Coord
- > >
{
typedef GenericInterval<Coord> Base;
public:
diff --git a/src/2geom/linear.h b/src/2geom/linear.h
index df6dd9904..448ab3bb7 100644
--- a/src/2geom/linear.h
+++ b/src/2geom/linear.h
@@ -55,7 +55,7 @@ class SBasis;
class Linear{
public:
double a[2];
- Linear() {}
+ Linear() { a[0] = 0; a[1] = 0; }
Linear(double aa, double b) {a[0] = aa; a[1] = b;}
Linear(double aa) {a[0] = aa; a[1] = aa;}
diff --git a/src/2geom/rect.h b/src/2geom/rect.h
index f7d331523..b79a0a04f 100644
--- a/src/2geom/rect.h
+++ b/src/2geom/rect.h
@@ -59,7 +59,6 @@ typedef GenericOptRect<Coord> OptRect;
*/
class Rect
: public GenericRect<Coord>
- , boost::multipliable< Rect, Affine >
{
typedef GenericRect<Coord> Base;
public:
diff --git a/src/2geom/transforms.h b/src/2geom/transforms.h
index 5627e8b6f..eaf869056 100644
--- a/src/2geom/transforms.h
+++ b/src/2geom/transforms.h
@@ -45,10 +45,11 @@ namespace Geom {
* @ingroup Concepts */
template <typename T>
struct TransformConcept {
- T t;
+ T t, t2;
Affine m;
Point p;
bool bool_;
+ Coord epsilon;
void constraints() {
m = t; //implicit conversion
m *= t;
@@ -63,6 +64,8 @@ struct TransformConcept {
bool_ = (t != t);
t = T::identity();
t = t.inverse();
+ bool_ = are_near(t, t2);
+ bool_ = are_near(t, t2, epsilon);
}
};
@@ -130,6 +133,10 @@ public:
friend class Point;
};
+inline bool are_near(Translate const &a, Translate const &b, Coord eps=EPSILON) {
+ return are_near(a[X], b[X], eps) && are_near(a[Y], b[Y], eps);
+}
+
/** @brief Scaling from the origin.
* During scaling, the point (0,0) will not move. To obtain a scale with a different
* invariant point, combine with translation to the origin and back.
@@ -164,6 +171,10 @@ public:
friend class Point;
};
+inline bool are_near(Scale const &a, Scale const &b, Coord eps=EPSILON) {
+ return are_near(a[X], b[X], eps) && are_near(a[Y], b[Y], eps);
+}
+
/** @brief Rotation around the origin.
* Combine with translations to the origin and back to get a rotation around a different point.
* @ingroup Transforms */
@@ -207,6 +218,10 @@ public:
friend class Point;
};
+inline bool are_near(Rotate const &a, Rotate const &b, Coord eps=EPSILON) {
+ return are_near(a[X], b[X], eps) && are_near(a[Y], b[Y], eps);
+}
+
/** @brief Common base for shearing transforms.
* This class is an implementation detail and should not be used directly.
* @ingroup Transforms */
@@ -241,6 +256,10 @@ public:
operator Affine() const { Affine ret(1, 0, f, 1, 0, 0); return ret; }
};
+inline bool are_near(HShear const &a, HShear const &b, Coord eps=EPSILON) {
+ return are_near(a.factor(), b.factor(), eps);
+}
+
/** @brief Vertical shearing.
* Points on the Y axis will not move. Combine with translations to get a shear
* with a different invariant line.
@@ -253,6 +272,10 @@ public:
operator Affine() const { Affine ret(1, f, 0, 1, 0, 0); return ret; }
};
+inline bool are_near(VShear const &a, VShear const &b, Coord eps=EPSILON) {
+ return are_near(a.factor(), b.factor(), eps);
+}
+
/** @brief Combination of a translation and uniform scale.
* The translation part is applied first, then the result is scaled from the new origin.
* This way when the class is used to accumulate a zoom transform, trans always points
@@ -295,6 +318,11 @@ public:
friend class Affine;
};
+inline bool are_near(Zoom const &a, Zoom const &b, Coord eps=EPSILON) {
+ return are_near(a.scale(), b.scale(), eps) &&
+ are_near(a.translation(), b.translation(), eps);
+}
+
/** @brief Specialization of exponentiation for Scale.
* @relates Scale */
template<>
diff --git a/src/context-fns.h b/src/context-fns.h
index c86640aba..c56c67a27 100644
--- a/src/context-fns.h
+++ b/src/context-fns.h
@@ -16,6 +16,7 @@
struct SPDesktop;
struct SPItem;
+struct SPEventContext;
const double goldenratio = 1.61803398874989484820; // golden ratio
diff --git a/src/desktop.cpp b/src/desktop.cpp
index 19504fa81..ca5fdc63b 100644
--- a/src/desktop.cpp
+++ b/src/desktop.cpp
@@ -59,55 +59,56 @@
#include <2geom/transforms.h>
#include <2geom/rect.h>
-#include "macros.h"
-#include "inkscape-private.h"
-#include "desktop.h"
+
+#include "box3d-context.h"
+#include "color.h"
#include "desktop-events.h"
+#include "desktop.h"
#include "desktop-handles.h"
-#include "document.h"
-#include "message-stack.h"
-#include "selection.h"
-#include "select-context.h"
-#include "sp-namedview.h"
-#include "color.h"
-#include "sp-item-group.h"
-#include "preferences.h"
-#include "object-hierarchy.h"
-#include "helper/units.h"
+#include "desktop-style.h"
+#include "device-manager.h"
#include "display/canvas-arena.h"
-#include "display/nr-arena.h"
-#include "display/gnome-canvas-acetate.h"
-#include "display/sodipodi-ctrlrect.h"
-#include "display/sp-canvas-util.h"
+#include "display/canvas-grid.h"
#include "display/canvas-temporary-item-list.h"
+#include "display/drawing-group.h"
+#include "display/gnome-canvas-acetate.h"
+#include "display/drawing.h"
#include "display/snap-indicator.h"
+#include "display/sodipodi-ctrlrect.h"
#include "display/sp-canvas-group.h"
-#include "ui/dialog/dialog-manager.h"
-#include "xml/repr.h"
-#include "message-context.h"
-#include "device-manager.h"
+#include "display/sp-canvas.h"
+#include "display/sp-canvas-util.h"
+#include "document.h"
+#include "event-log.h"
+#include "helper/units.h"
+#include "inkscape-private.h"
#include "layer-fns.h"
#include "layer-manager.h"
+#include "macros.h"
+#include "message-context.h"
+#include "message-stack.h"
+#include "object-hierarchy.h"
+#include "preferences.h"
#include "resource-manager.h"
-#include "event-log.h"
-#include "display/canvas-grid.h"
-#include "widgets/desktop-widget.h"
-#include "box3d-context.h"
-#include "desktop-style.h"
+#include "select-context.h"
+#include "selection.h"
+#include "sp-item-group.h"
#include "sp-item-group.h"
+#include "sp-namedview.h"
#include "sp-root.h"
+#include "ui/dialog/dialog-manager.h"
+#include "widgets/desktop-widget.h"
+#include "xml/repr.h"
// TODO those includes are only for node tool quick zoom. Remove them after fixing it.
#include "ui/tool/node-tool.h"
#include "ui/tool/control-point-selection.h"
-#include "display/sp-canvas.h"
-
namespace Inkscape { namespace XML { class Node; }}
// Callback declarations
static void _onSelectionChanged (Inkscape::Selection *selection, SPDesktop *desktop);
-static gint _arena_handler (SPCanvasArena *arena, NRArenaItem *ai, GdkEvent *event, SPDesktop *desktop);
+static gint _arena_handler (SPCanvasArena *arena, Inkscape::DrawingItem *ai, GdkEvent *event, SPDesktop *desktop);
static void _layer_activated(SPObject *layer, SPDesktop *desktop);
static void _layer_deactivated(SPObject *layer, SPDesktop *desktop);
static void _layer_hierarchy_changed(SPObject *top, SPObject *bottom, SPDesktop *desktop);
@@ -158,7 +159,7 @@ SPDesktop::SPDesktop() :
_layer_hierarchy( 0 ),
_reconstruction_old_layer_id(), // an id attribute is not allowed to be the empty string
_display_mode(Inkscape::RENDERMODE_NORMAL),
- _display_color_mode(Inkscape::COLORRENDERMODE_NORMAL),
+ _display_color_mode(Inkscape::COLORMODE_NORMAL),
_widget( 0 ),
_inkscape( 0 ),
_guides_message_context( 0 ),
@@ -229,7 +230,7 @@ SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas, Inkscape::UI::View::EditWid
drawing = sp_canvas_item_new (main, SP_TYPE_CANVAS_ARENA, NULL);
g_signal_connect (G_OBJECT (drawing), "arena_event", G_CALLBACK (_arena_handler), this);
- SP_CANVAS_ARENA (drawing)->arena->delta = prefs->getDouble("/options/cursortolerance/value", 1.0); // default is 1 px
+ SP_CANVAS_ARENA (drawing)->drawing.delta = prefs->getDouble("/options/cursortolerance/value", 1.0); // default is 1 px
if (prefs->getBool("/options/startmode/outline")) {
// Start in outline mode
@@ -285,12 +286,12 @@ SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas, Inkscape::UI::View::EditWid
_modified_connection = namedview->connectModified(sigc::bind<2>(sigc::ptr_fun(&_namedview_modified), this));
- NRArenaItem *ai = document->getRoot()->invoke_show(
- SP_CANVAS_ARENA (drawing)->arena,
+ Inkscape::DrawingItem *ai = document->getRoot()->invoke_show(
+ SP_CANVAS_ARENA (drawing)->drawing,
dkey,
SP_ITEM_SHOW_DISPLAY);
if (ai) {
- nr_arena_item_add_child (SP_CANVAS_ARENA (drawing)->root, ai, NULL);
+ SP_CANVAS_ARENA (drawing)->drawing.root()->prependChild(ai);
}
namedview->show(this);
@@ -403,6 +404,7 @@ void SPDesktop::destroy()
if (drawing) {
doc()->getRoot()->invoke_hide(dkey);
+ g_object_unref(drawing);
drawing = NULL;
}
@@ -454,14 +456,14 @@ SPDesktop::remove_temporary_canvasitem (Inkscape::Display::TemporaryItem * tempi
}
void SPDesktop::_setDisplayMode(Inkscape::RenderMode mode) {
- SP_CANVAS_ARENA (drawing)->arena->rendermode = mode;
+ SP_CANVAS_ARENA (drawing)->drawing.setRenderMode(mode);
canvas->rendermode = mode;
_display_mode = mode;
sp_canvas_item_affine_absolute (SP_CANVAS_ITEM (main), _d2w); // redraw
_widget->setTitle( sp_desktop_document(this)->getName() );
}
-void SPDesktop::_setDisplayColorMode(Inkscape::ColorRenderMode mode) {
- SP_CANVAS_ARENA (drawing)->arena->colorrendermode = mode;
+void SPDesktop::_setDisplayColorMode(Inkscape::ColorMode mode) {
+ SP_CANVAS_ARENA (drawing)->drawing.setColorMode(mode);
canvas->colorrendermode = mode;
_display_color_mode = mode;
sp_canvas_item_affine_absolute (SP_CANVAS_ITEM (main), _d2w); // redraw
@@ -485,15 +487,15 @@ void SPDesktop::displayModeToggle() {
}
void SPDesktop::displayColorModeToggle() {
switch (_display_color_mode) {
- case Inkscape::COLORRENDERMODE_NORMAL:
- _setDisplayColorMode(Inkscape::COLORRENDERMODE_GRAYSCALE);
+ case Inkscape::COLORMODE_NORMAL:
+ _setDisplayColorMode(Inkscape::COLORMODE_GRAYSCALE);
break;
- case Inkscape::COLORRENDERMODE_GRAYSCALE:
- _setDisplayColorMode(Inkscape::COLORRENDERMODE_NORMAL);
+ case Inkscape::COLORMODE_GRAYSCALE:
+ _setDisplayColorMode(Inkscape::COLORMODE_NORMAL);
break;
-// case Inkscape::COLORRENDERMODE_PRINT_COLORS_PREVIEW:
+// case Inkscape::COLORMODE_PRINT_COLORS_PREVIEW:
default:
- _setDisplayColorMode(Inkscape::COLORRENDERMODE_NORMAL);
+ _setDisplayColorMode(Inkscape::COLORMODE_NORMAL);
}
}
@@ -1562,18 +1564,18 @@ SPDesktop::setDocument (SPDocument *doc)
/// are surely more safe methods to accomplish this.
// TODO since the comment had reversed logic, check the intent of this block of code:
if (drawing) {
- NRArenaItem *ai = 0;
+ Inkscape::DrawingItem *ai = 0;
namedview = sp_document_namedview (doc, NULL);
_modified_connection = namedview->connectModified(sigc::bind<2>(sigc::ptr_fun(&_namedview_modified), this));
number = namedview->getViewCount();
ai = doc->getRoot()->invoke_show(
- SP_CANVAS_ARENA (drawing)->arena,
+ SP_CANVAS_ARENA (drawing)->drawing,
dkey,
SP_ITEM_SHOW_DISPLAY);
if (ai) {
- nr_arena_item_add_child (SP_CANVAS_ARENA (drawing)->root, ai, NULL);
+ SP_CANVAS_ARENA (drawing)->drawing.root()->prependChild(ai);
}
namedview->show(this);
/* Ugly hack */
@@ -1662,10 +1664,10 @@ _onSelectionChanged
* \todo fixme
*/
static gint
-_arena_handler (SPCanvasArena */*arena*/, NRArenaItem *ai, GdkEvent *event, SPDesktop *desktop)
+_arena_handler (SPCanvasArena */*arena*/, Inkscape::DrawingItem *ai, GdkEvent *event, SPDesktop *desktop)
{
if (ai) {
- SPItem *spi = (SPItem*)NR_ARENA_ITEM_GET_DATA (ai);
+ SPItem *spi = (SPItem*) ai->data();
return sp_event_context_item_handler (desktop->event_context, spi, event);
} else {
return sp_event_context_root_handler (desktop->event_context, event);
@@ -1783,9 +1785,9 @@ _namedview_modified (SPObject *obj, guint flags, SPDesktop *desktop)
SP_RGBA32_G_U(nv->pagecolor) +
SP_RGBA32_B_U(nv->pagecolor)) >= 384) {
// the background color is light or transparent, use black outline
- SP_CANVAS_ARENA (desktop->drawing)->arena->outlinecolor = prefs->getInt("/options/wireframecolors/onlight", 0xff);
+ SP_CANVAS_ARENA (desktop->drawing)->drawing.outlinecolor = prefs->getInt("/options/wireframecolors/onlight", 0xff);
} else { // use white outline
- SP_CANVAS_ARENA (desktop->drawing)->arena->outlinecolor = prefs->getInt("/options/wireframecolors/ondark", 0xffffffff);
+ SP_CANVAS_ARENA (desktop->drawing)->drawing.outlinecolor = prefs->getInt("/options/wireframecolors/ondark", 0xffffffff);
}
}
}
diff --git a/src/desktop.h b/src/desktop.h
index 5fd786936..5dcd014ca 100644
--- a/src/desktop.h
+++ b/src/desktop.h
@@ -212,19 +212,19 @@ public:
Inkscape::RenderMode _display_mode;
Inkscape::RenderMode getMode() const { return _display_mode; }
- void _setDisplayColorMode(Inkscape::ColorRenderMode mode);
+ void _setDisplayColorMode(Inkscape::ColorMode mode);
void setDisplayColorModeNormal() {
- _setDisplayColorMode(Inkscape::COLORRENDERMODE_NORMAL);
+ _setDisplayColorMode(Inkscape::COLORMODE_NORMAL);
}
void setDisplayColorModeGrayscale() {
- _setDisplayColorMode(Inkscape::COLORRENDERMODE_GRAYSCALE);
+ _setDisplayColorMode(Inkscape::COLORMODE_GRAYSCALE);
}
// void setDisplayColorModePrintColorsPreview() {
-// _setDisplayColorMode(Inkscape::COLORRENDERMODE_PRINT_COLORS_PREVIEW);
+// _setDisplayColorMode(Inkscape::COLORMODE_PRINT_COLORS_PREVIEW);
// }
void displayColorModeToggle();
- Inkscape::ColorRenderMode _display_color_mode;
- Inkscape::ColorRenderMode getColorMode() const { return _display_color_mode; }
+ Inkscape::ColorMode _display_color_mode;
+ Inkscape::ColorMode getColorMode() const { return _display_color_mode; }
Inkscape::UI::Widget::Dock* getDock() { return _widget->getDock(); }
diff --git a/src/dialogs/clonetiler.cpp b/src/dialogs/clonetiler.cpp
index 194f341e1..109b235d0 100644
--- a/src/dialogs/clonetiler.cpp
+++ b/src/dialogs/clonetiler.cpp
@@ -14,6 +14,8 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
+
+#include <climits>
#include <glib/gmem.h>
#include <gtk/gtk.h>
#include <glibmm/i18n.h>
@@ -23,8 +25,9 @@
#include "desktop-handles.h"
#include "dialog-events.h"
#include "display/cairo-utils.h"
-#include "display/nr-arena.h"
-#include "display/nr-arena-item.h"
+#include "display/drawing.h"
+#include "display/drawing-context.h"
+#include "display/drawing-item.h"
#include "document.h"
#include "filter-chemistry.h"
#include "helper/unit-menu.h"
@@ -829,15 +832,14 @@ static bool clonetiler_is_a_clone_of(SPObject *tile, SPObject *obj)
return result;
}
-static NRArena const *trace_arena = NULL;
+static Inkscape::Drawing *trace_drawing = NULL;
static unsigned trace_visionkey;
-static NRArenaItem *trace_root;
static gdouble trace_zoom;
-static SPDocument *trace_doc;
+static SPDocument *trace_doc = NULL;
static void clonetiler_trace_hide_tiled_clones_recursively(SPObject *from)
{
- if (!trace_arena)
+ if (!trace_drawing)
return;
for (SPObject *o = from->firstChild(); o != NULL; o = o->next) {
@@ -849,11 +851,11 @@ static void clonetiler_trace_hide_tiled_clones_recursively(SPObject *from)
static void clonetiler_trace_setup(SPDocument *doc, gdouble zoom, SPItem *original)
{
- trace_arena = NRArena::create();
+ trace_drawing = new Inkscape::Drawing();
/* Create ArenaItem and set transform */
trace_visionkey = SPItem::display_key_new(1);
trace_doc = doc;
- trace_root = trace_doc->getRoot()->invoke_show((NRArena *) trace_arena, trace_visionkey, SP_ITEM_SHOW_DISPLAY);
+ trace_drawing->setRoot(trace_doc->getRoot()->invoke_show(*trace_drawing, trace_visionkey, SP_ITEM_SHOW_DISPLAY));
// hide the (current) original and any tiled clones, we only want to pick the background
original->invoke_hide(trace_visionkey);
@@ -867,37 +869,22 @@ static void clonetiler_trace_setup(SPDocument *doc, gdouble zoom, SPItem *origin
static guint32 clonetiler_trace_pick(Geom::Rect box)
{
- if (!trace_arena) {
+ if (!trace_drawing) {
return 0;
}
- Geom::Affine t(Geom::Scale(trace_zoom, trace_zoom));
- nr_arena_item_set_transform(trace_root, &t);
- NRGC gc(NULL);
- gc.transform.setIdentity();
- nr_arena_item_invoke_update( trace_root, NULL, &gc,
- NR_ARENA_ITEM_STATE_ALL,
- NR_ARENA_ITEM_STATE_NONE );
+ trace_drawing->root()->setTransform(Geom::Scale(trace_zoom));
+ trace_drawing->update();
/* Item integer bbox in points */
- NRRectL ibox;
- ibox.x0 = floor(trace_zoom * box[Geom::X].min());
- ibox.y0 = floor(trace_zoom * box[Geom::Y].min());
- ibox.x1 = ceil(trace_zoom * box[Geom::X].max());
- ibox.y1 = ceil(trace_zoom * box[Geom::Y].max());
+ Geom::IntRect ibox = (box * Geom::Scale(trace_zoom)).roundOutwards();
/* Find visible area */
- int width = ibox.x1 - ibox.x0;
- int height = ibox.y1 - ibox.y0;
- double R = 0, G = 0, B = 0, A = 0;
-
- cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
- cairo_t *ct = cairo_create(s);
- cairo_translate(ct, -ibox.x0, -ibox.y0);
+ cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, ibox.width(), ibox.height());
+ Inkscape::DrawingContext ct(s, ibox.min());
/* Render */
- nr_arena_item_invoke_render(ct, trace_root, &ibox, NULL,
- NR_ARENA_ITEM_RENDER_NO_CACHE );
- cairo_destroy(ct);
+ trace_drawing->render(ct, ibox);
+ double R = 0, G = 0, B = 0, A = 0;
ink_cairo_surface_average_color(s, R, G, B, A);
cairo_surface_destroy(s);
@@ -908,10 +895,9 @@ static void clonetiler_trace_finish()
{
if (trace_doc) {
trace_doc->getRoot()->invoke_hide(trace_visionkey);
- }
- if (trace_arena) {
- ((NRObject *) trace_arena)->unreference();
- trace_arena = NULL;
+ delete trace_drawing;
+ trace_doc = NULL;
+ trace_drawing = NULL;
}
}
diff --git a/src/display/Makefile_insert b/src/display/Makefile_insert
index fc7c8e9ab..1c7a21dae 100644
--- a/src/display/Makefile_insert
+++ b/src/display/Makefile_insert
@@ -23,6 +23,22 @@ ink_common_sources += \
display/canvas-text.h \
display/curve.cpp \
display/curve.h \
+ display/drawing.cpp \
+ display/drawing.h \
+ display/drawing-context.cpp \
+ display/drawing-context.h \
+ display/drawing-group.cpp \
+ display/drawing-group.h \
+ display/drawing-image.cpp \
+ display/drawing-image.h \
+ display/drawing-item.cpp \
+ display/drawing-item.h \
+ display/drawing-shape.cpp \
+ display/drawing-shape.h \
+ display/drawing-surface.cpp \
+ display/drawing-surface.h \
+ display/drawing-text.cpp \
+ display/drawing-text.h \
display/gnome-canvas-acetate.cpp \
display/gnome-canvas-acetate.h \
display/grayscale.cpp \
@@ -31,19 +47,7 @@ ink_common_sources += \
display/guideline.h \
display/nr-3dutils.cpp \
display/nr-3dutils.h \
- display/nr-arena.cpp \
display/nr-arena-forward.h \
- display/nr-arena-glyphs.cpp \
- display/nr-arena-glyphs.h \
- display/nr-arena-group.cpp \
- display/nr-arena-group.h \
- display/nr-arena.h \
- display/nr-arena-image.cpp \
- display/nr-arena-image.h \
- display/nr-arena-item.cpp \
- display/nr-arena-item.h \
- display/nr-arena-shape.cpp \
- display/nr-arena-shape.h \
display/nr-filter-blend.cpp \
display/nr-filter-blend.h \
display/nr-filter-colormatrix.cpp \
diff --git a/src/display/cairo-templates.h b/src/display/cairo-templates.h
index a79f58548..d4c8e1493 100644
--- a/src/display/cairo-templates.h
+++ b/src/display/cairo-templates.h
@@ -12,6 +12,10 @@
#ifndef SEEN_INKSCAPE_DISPLAY_CAIRO_TEMPLATES_H
#define SEEN_INKSCAPE_DISPLAY_CAIRO_TEMPLATES_H
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
#ifdef HAVE_OPENMP
#include <omp.h>
#include "preferences.h"
diff --git a/src/display/canvas-arena.cpp b/src/display/canvas-arena.cpp
index dd4a4ed5c..4688a58e3 100644
--- a/src/display/canvas-arena.cpp
+++ b/src/display/canvas-arena.cpp
@@ -15,10 +15,15 @@
#include "display/display-forward.h"
#include "display/sp-canvas-util.h"
#include "helper/sp-marshal.h"
-#include "display/nr-arena.h"
-#include "display/nr-arena-group.h"
#include "display/canvas-arena.h"
#include "display/cairo-utils.h"
+#include "display/drawing-context.h"
+#include "display/drawing-item.h"
+#include "display/drawing-group.h"
+#include "display/drawing-surface.h"
+#include "preferences.h"
+
+using namespace Inkscape;
enum {
ARENA_EVENT,
@@ -29,28 +34,42 @@ static void sp_canvas_arena_class_init(SPCanvasArenaClass *klass);
static void sp_canvas_arena_init(SPCanvasArena *group);
static void sp_canvas_arena_destroy(GtkObject *object);
+static void sp_canvas_arena_item_deleted(SPCanvasArena *arena, Inkscape::DrawingItem *item);
static void sp_canvas_arena_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags);
static void sp_canvas_arena_render (SPCanvasItem *item, SPCanvasBuf *buf);
-static void sp_canvas_arena_render_cache (SPCanvasItem *item, Geom::IntRect const &area);
-static void sp_canvas_arena_dirty_cache (SPCanvasArena *arena, NRRectL *area);
static double sp_canvas_arena_point (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_item);
-static void sp_canvas_arena_visible_area_changed (SPCanvasItem *item, Geom::IntRect const &old_area, Geom::IntRect const &new_area);
+static void sp_canvas_arena_viewbox_changed (SPCanvasItem *item, Geom::IntRect const &new_area);
static gint sp_canvas_arena_event (SPCanvasItem *item, GdkEvent *event);
static gint sp_canvas_arena_send_event (SPCanvasArena *arena, GdkEvent *event);
-static void sp_canvas_arena_request_update (NRArena *arena, NRArenaItem *item, void *data);
-static void sp_canvas_arena_request_render (NRArena *arena, NRRectL *area, void *data);
-
-NRArenaEventVector carenaev = {
- {NULL},
- sp_canvas_arena_request_update,
- sp_canvas_arena_request_render
-};
+static void sp_canvas_arena_request_update (SPCanvasArena *ca, DrawingItem *item);
+static void sp_canvas_arena_request_render (SPCanvasArena *ca, Geom::IntRect const &area);
static SPCanvasItemClass *parent_class;
static guint signals[LAST_SIGNAL] = {0};
+struct CachePrefObserver : public Inkscape::Preferences::Observer {
+ CachePrefObserver(SPCanvasArena *arena)
+ : Inkscape::Preferences::Observer("/options/renderingcache")
+ , _arena(arena)
+ {
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ std::vector<Inkscape::Preferences::Entry> v = prefs->getAllEntries(observed_path);
+ for (unsigned i=0; i<v.size(); ++i) {
+ notify(v[i]);
+ }
+ prefs->addObserver(*this);
+ }
+ void notify(Preferences::Entry const &v) {
+ Glib::ustring name = v.getEntryName();
+ if (name == "size") {
+ _arena->drawing.setCacheBudget((1 << 20) * v.getIntLimited(64, 0, 4096));
+ }
+ }
+ SPCanvasArena *_arena;
+};
+
GType
sp_canvas_arena_get_type (void)
{
@@ -96,7 +115,7 @@ sp_canvas_arena_class_init (SPCanvasArenaClass *klass)
item_class->render = sp_canvas_arena_render;
item_class->point = sp_canvas_arena_point;
item_class->event = sp_canvas_arena_event;
- item_class->visible_area_changed = sp_canvas_arena_visible_area_changed;
+ item_class->viewbox_changed = sp_canvas_arena_viewbox_changed;
}
static void
@@ -104,17 +123,28 @@ sp_canvas_arena_init (SPCanvasArena *arena)
{
arena->sticky = FALSE;
- arena->arena = NRArena::create();
- arena->arena->canvasarena = arena;
- arena->root = NRArenaGroup::create(arena->arena);
- nr_arena_group_set_transparent (NR_ARENA_GROUP (arena->root), TRUE);
+ new (&arena->drawing) Inkscape::Drawing(arena);
- arena->active = NULL;
- arena->cache = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1);
- arena->cache_area = Geom::IntRect::from_xywh(0,0,1,1);
- arena->dirty = cairo_region_create();
+ Inkscape::DrawingGroup *root = new DrawingGroup(arena->drawing);
+ root->setPickChildren(true);
+ arena->drawing.setRoot(root);
+
+ arena->observer = new CachePrefObserver(arena);
+
+ arena->drawing.signal_request_update.connect(
+ sigc::bind<0>(
+ sigc::ptr_fun(&sp_canvas_arena_request_update),
+ arena));
+ arena->drawing.signal_request_render.connect(
+ sigc::bind<0>(
+ sigc::ptr_fun(&sp_canvas_arena_request_render),
+ arena));
+ arena->drawing.signal_item_deleted.connect(
+ sigc::bind<0>(
+ sigc::ptr_fun(&sp_canvas_arena_item_deleted),
+ arena));
- nr_active_object_add_listener ((NRActiveObject *) arena->arena, (NRObjectEventVector *) &carenaev, sizeof (carenaev), arena);
+ arena->active = NULL;
}
static void
@@ -122,27 +152,8 @@ sp_canvas_arena_destroy (GtkObject *object)
{
SPCanvasArena *arena = SP_CANVAS_ARENA (object);
- if (arena->active) {
- nr_object_unref ((NRObject *) arena->active);
- arena->active = NULL;
- }
-
- if (arena->root) {
- nr_arena_item_unref (arena->root);
- arena->root = NULL;
- }
-
- if (arena->arena) {
- nr_active_object_remove_listener_by_data ((NRActiveObject *) arena->arena, arena);
-
- nr_object_unref ((NRObject *) arena->arena);
- arena->arena = NULL;
- }
- if (arena->cache) {
- cairo_surface_destroy(arena->cache);
- arena->cache = NULL;
- }
- cairo_region_destroy(arena->dirty);
+ delete arena->observer;
+ arena->drawing.~Drawing();
if (GTK_OBJECT_CLASS (parent_class)->destroy)
(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
@@ -156,21 +167,22 @@ sp_canvas_arena_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned
if (((SPCanvasItemClass *) parent_class)->update)
(* ((SPCanvasItemClass *) parent_class)->update) (item, affine, flags);
- arena->gc.transform = affine;
+ arena->ctx.ctm = affine;
- guint reset;
- reset = (flags & SP_CANVAS_UPDATE_AFFINE)? NR_ARENA_ITEM_STATE_ALL : NR_ARENA_ITEM_STATE_NONE;
+ unsigned reset = flags & SP_CANVAS_UPDATE_AFFINE ? DrawingItem::STATE_ALL : 0;
+ arena->drawing.update(Geom::IntRect::infinite(), arena->ctx, DrawingItem::STATE_ALL, reset);
- nr_arena_item_invoke_update (arena->root, NULL, &arena->gc, NR_ARENA_ITEM_STATE_ALL, reset);
-
- item->x1 = arena->root->bbox.x0 - 1;
- item->y1 = arena->root->bbox.y0 - 1;
- item->x2 = arena->root->bbox.x1 + 1;
- item->y2 = arena->root->bbox.y1 + 1;
+ Geom::OptIntRect b = arena->drawing.root()->visualBounds();
+ if (b) {
+ item->x1 = b->left() - 1;
+ item->y1 = b->top() - 1;
+ item->x2 = b->right() + 1;
+ item->y2 = b->bottom() + 1;
+ }
if (arena->cursor) {
/* Mess with enter/leave notifiers */
- NRArenaItem *new_arena = nr_arena_item_invoke_pick (arena->root, arena->c, arena->arena->delta, arena->sticky);
+ DrawingItem *new_arena = arena->drawing.pick(arena->c, arena->drawing.delta, arena->sticky);
if (new_arena != arena->active) {
GdkEventCrossing ec;
ec.window = GTK_WIDGET (item->canvas)->window;
@@ -184,10 +196,7 @@ sp_canvas_arena_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned
ec.type = GDK_LEAVE_NOTIFY;
sp_canvas_arena_send_event (arena, (GdkEvent *) &ec);
}
- /* fixme: This is not optimal - better track ::destroy (Lauris) */
- if (arena->active) nr_object_unref ((NRObject *) arena->active);
arena->active = new_arena;
- if (arena->active) nr_object_ref ((NRObject *) arena->active);
if (arena->active) {
ec.type = GDK_ENTER_NOTIFY;
sp_canvas_arena_send_event (arena, (GdkEvent *) &ec);
@@ -197,76 +206,26 @@ sp_canvas_arena_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned
}
static void
+sp_canvas_arena_item_deleted(SPCanvasArena *arena, Inkscape::DrawingItem *item)
+{
+ if (arena->active == item) {
+ arena->active = NULL;
+ }
+}
+
+static void
sp_canvas_arena_render (SPCanvasItem *item, SPCanvasBuf *buf)
{
+ // todo: handle NR_ARENA_ITEM_RENDER_NO_CACHE
SPCanvasArena *arena = SP_CANVAS_ARENA (item);
- //SPCanvas *canvas = item->canvas;
-
- //nr_arena_item_invoke_update (arena->root, NULL, &arena->gc,
- // NR_ARENA_ITEM_STATE_BBOX | NR_ARENA_ITEM_STATE_RENDER,
- // NR_ARENA_ITEM_STATE_NONE);
Geom::OptIntRect r = buf->rect;
if (!r || r->hasZeroArea()) return;
-
- cairo_rectangle_int_t crect;
- crect.x = r->left();
- crect.y = r->top();
- crect.width = r->width();
- crect.height = r->height();
- if (cairo_region_contains_rectangle(arena->dirty, &crect) != CAIRO_REGION_OVERLAP_OUT) {
- sp_canvas_arena_render_cache(item, *r);
- cairo_region_subtract_rectangle(arena->dirty, &crect);
- }
- cairo_save(buf->ct);
- cairo_translate(buf->ct, -r->left(), -r->top());
- //cairo_rectangle(buf->ct, r->left(), r->top(), r->width(), r->height());
- //cairo_clip(buf->ct);
- cairo_set_source_surface(buf->ct, arena->cache, arena->cache_area.left(), arena->cache_area.top());
- cairo_paint(buf->ct);
- //nr_arena_item_invoke_render (buf->ct, arena->root, &area, NULL, 0);
- cairo_restore(buf->ct);
-}
+ Inkscape::DrawingContext ct(buf->ct, r->min());
-static void sp_canvas_arena_render_cache (SPCanvasItem *item, Geom::IntRect const &area)
-{
- SPCanvasArena *arena = SP_CANVAS_ARENA (item);
-
- Geom::OptIntRect r = Geom::intersect(arena->cache_area, area);
- if (!r || r->hasZeroArea()) return; // nothing to do
-
- cairo_t *ct = cairo_create(arena->cache);
- cairo_translate(ct, -arena->cache_area.left(), -arena->cache_area.top());
-
- // clear area to paint
- cairo_rectangle(ct, area.left(), area.top(), area.width(), area.height());
- cairo_clip(ct);
- cairo_save(ct);
- cairo_set_source_rgba(ct, 0,0,0,0);
- cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE);
- cairo_paint(ct);
- cairo_restore(ct);
-
- NRRectL nr_area(r);
-
- nr_arena_item_invoke_update (arena->root, NULL, &arena->gc,
- NR_ARENA_ITEM_STATE_BBOX | NR_ARENA_ITEM_STATE_RENDER,
- NR_ARENA_ITEM_STATE_NONE);
- nr_arena_item_invoke_render (ct, arena->root, &nr_area, NULL, 0);
-
- cairo_destroy(ct);
-}
-
-static void
-sp_canvas_arena_dirty_cache (SPCanvasArena *arena, NRRectL *area)
-{
- cairo_rectangle_int_t rect;
- rect.x = area->x0;
- rect.y = area->y0;
- rect.width = area->x1 - area->x0;
- rect.height = area->y1 - area->y0;
- cairo_region_union_rectangle(arena->dirty, &rect);
+ arena->drawing.update(Geom::IntRect::infinite(), arena->ctx);
+ arena->drawing.render(ct, *r);
}
static double
@@ -274,11 +233,8 @@ sp_canvas_arena_point (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_
{
SPCanvasArena *arena = SP_CANVAS_ARENA (item);
- nr_arena_item_invoke_update (arena->root, NULL, &arena->gc,
- NR_ARENA_ITEM_STATE_BBOX | NR_ARENA_ITEM_STATE_PICK,
- NR_ARENA_ITEM_STATE_NONE);
-
- NRArenaItem *picked = nr_arena_item_invoke_pick (arena->root, p, arena->arena->delta, arena->sticky);
+ arena->drawing.update(Geom::IntRect::infinite(), arena->ctx, DrawingItem::STATE_PICK);
+ DrawingItem *picked = arena->drawing.pick(p, arena->drawing.delta, arena->sticky);
arena->picked = picked;
@@ -291,70 +247,20 @@ sp_canvas_arena_point (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_
}
static void
-sp_canvas_arena_visible_area_changed (SPCanvasItem *item, Geom::IntRect const &old_area, Geom::IntRect const &new_area)
+sp_canvas_arena_viewbox_changed (SPCanvasItem *item, Geom::IntRect const &new_area)
{
SPCanvasArena *arena = SP_CANVAS_ARENA(item);
-
- cairo_surface_t *new_cache = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
- new_area.width(), new_area.height());
- cairo_t *ct = cairo_create(new_cache);
- cairo_set_source_surface(ct, arena->cache, old_area.left() - new_area.left(), old_area.top() - new_area.top());
- cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE);
- cairo_paint(ct);
- cairo_destroy(ct);
- cairo_surface_destroy(arena->cache);
- arena->cache = new_cache;
- arena->cache_area = new_area;
-
- cairo_rectangle_int_t crect;
- crect.x = new_area.left();
- crect.y = new_area.top();
- crect.width = new_area.width();
- crect.height = new_area.height();
- cairo_region_intersect_rectangle(arena->dirty, &crect);
-
- // invalidate newly exposed areas
- /*
- * +----------------------+
- * | top strip |
- * +-------+------+-------+
- * | | | |
- * | left | old | right |
- * | strip | area | strip |
- * | | | |
- * +-------+------+-------+
- * | bottom strip |
- * +----------------------+
- */
-
- // top strip
- if (new_area.top() < old_area.top()) {
- NRRectL top_strip(new_area.left(), new_area.top(), new_area.right(), old_area.top());
- sp_canvas_arena_dirty_cache(arena, &top_strip);
- }
- // left strip
- if (new_area.left() < old_area.left()) {
- NRRectL left_strip(new_area.left(), std::max(new_area.top(), old_area.top()),
- old_area.left(), std::min(new_area.bottom(), old_area.bottom()));
- sp_canvas_arena_dirty_cache(arena, &left_strip);
- }
- // right strip
- if (new_area.right() > old_area.right()) {
- NRRectL right_strip(old_area.right(), std::max(new_area.top(), old_area.top()),
- new_area.right(), std::min(new_area.bottom(), old_area.bottom()));
- sp_canvas_arena_dirty_cache(arena, &right_strip);
- }
- // bottom strip
- if (new_area.bottom() > old_area.bottom()) {
- NRRectL bottom_strip(new_area.left(), old_area.bottom(), new_area.right(), new_area.bottom());
- sp_canvas_arena_dirty_cache(arena, &bottom_strip);
- }
+ // make the cache limit larger than screen to facilitate smooth scrolling
+ Geom::IntRect expanded = new_area;
+ Geom::IntPoint expansion(new_area.width()/2, new_area.height()/2);
+ expanded.expandBy(expansion);
+ arena->drawing.setCacheLimit(expanded);
}
static gint
sp_canvas_arena_event (SPCanvasItem *item, GdkEvent *event)
{
- NRArenaItem *new_arena;
+ Inkscape::DrawingItem *new_arena;
/* fixme: This sucks, we have to handle enter/leave notifiers */
SPCanvasArena *arena = SP_CANVAS_ARENA (item);
@@ -366,7 +272,6 @@ sp_canvas_arena_event (SPCanvasItem *item, GdkEvent *event)
if (!arena->cursor) {
if (arena->active) {
//g_warning ("Cursor entered to arena with already active item");
- nr_object_unref ((NRObject *) arena->active);
}
arena->cursor = TRUE;
@@ -374,9 +279,8 @@ sp_canvas_arena_event (SPCanvasItem *item, GdkEvent *event)
arena->c = Geom::Point(event->crossing.x, event->crossing.y);
/* fixme: Not sure abut this, but seems the right thing (Lauris) */
- nr_arena_item_invoke_update (arena->root, NULL, &arena->gc, NR_ARENA_ITEM_STATE_PICK, NR_ARENA_ITEM_STATE_NONE);
- arena->active = nr_arena_item_invoke_pick (arena->root, arena->c, arena->arena->delta, arena->sticky);
- if (arena->active) nr_object_ref ((NRObject *) arena->active);
+ arena->drawing.update(Geom::IntRect::infinite(), arena->ctx, DrawingItem::STATE_PICK, 0);
+ arena->active = arena->drawing.pick(arena->c, arena->drawing.delta, arena->sticky);
ret = sp_canvas_arena_send_event (arena, event);
}
break;
@@ -384,7 +288,6 @@ sp_canvas_arena_event (SPCanvasItem *item, GdkEvent *event)
case GDK_LEAVE_NOTIFY:
if (arena->cursor) {
ret = sp_canvas_arena_send_event (arena, event);
- if (arena->active) nr_object_unref ((NRObject *) arena->active);
arena->active = NULL;
arena->cursor = FALSE;
}
@@ -395,8 +298,8 @@ sp_canvas_arena_event (SPCanvasItem *item, GdkEvent *event)
arena->c = Geom::Point(event->motion.x, event->motion.y);
/* fixme: Not sure abut this, but seems the right thing (Lauris) */
- nr_arena_item_invoke_update (arena->root, NULL, &arena->gc, NR_ARENA_ITEM_STATE_PICK, NR_ARENA_ITEM_STATE_NONE);
- new_arena = nr_arena_item_invoke_pick (arena->root, arena->c, arena->arena->delta, arena->sticky);
+ arena->drawing.update(Geom::IntRect::infinite(), arena->ctx, DrawingItem::STATE_PICK);
+ new_arena = arena->drawing.pick(arena->c, arena->drawing.delta, arena->sticky);
if (new_arena != arena->active) {
GdkEventCrossing ec;
ec.window = event->motion.window;
@@ -410,9 +313,7 @@ sp_canvas_arena_event (SPCanvasItem *item, GdkEvent *event)
ec.type = GDK_LEAVE_NOTIFY;
ret = sp_canvas_arena_send_event (arena, (GdkEvent *) &ec);
}
- if (arena->active) nr_object_unref ((NRObject *) arena->active);
arena->active = new_arena;
- if (arena->active) nr_object_ref ((NRObject *) arena->active);
if (arena->active) {
ec.type = GDK_ENTER_NOTIFY;
ret = sp_canvas_arena_send_event (arena, (GdkEvent *) &ec);
@@ -442,17 +343,16 @@ sp_canvas_arena_send_event (SPCanvasArena *arena, GdkEvent *event)
}
static void
-sp_canvas_arena_request_update (NRArena */*arena*/, NRArenaItem */*item*/, void *data)
+sp_canvas_arena_request_update (SPCanvasArena *ca, DrawingItem */*item*/)
{
- sp_canvas_item_request_update (SP_CANVAS_ITEM (data));
+ sp_canvas_item_request_update (SP_CANVAS_ITEM (ca));
}
static void
-sp_canvas_arena_request_render (NRArena */*arena*/, NRRectL *area, void *data)
+sp_canvas_arena_request_render (SPCanvasArena *ca, Geom::IntRect const &area)
{
- if (!area) return;
- sp_canvas_arena_dirty_cache (SP_CANVAS_ARENA(data), area);
- sp_canvas_request_redraw (SP_CANVAS_ITEM (data)->canvas, area->x0, area->y0, area->x1, area->y1);
+ SPCanvas *canvas = SP_CANVAS_ITEM (ca)->canvas;
+ sp_canvas_request_redraw (canvas, area.left(), area.top(), area.right(), area.bottom());
}
void
@@ -481,13 +381,13 @@ sp_canvas_arena_render_surface (SPCanvasArena *ca, cairo_surface_t *surface, NRR
g_return_if_fail (ca != NULL);
g_return_if_fail (SP_IS_CANVAS_ARENA (ca));
- cairo_t *ct = cairo_create(surface);
- cairo_translate(ct, -r.x0, -r.y0);
- nr_arena_item_invoke_render (ct, ca->root, &r, NULL, 0);
- cairo_destroy(ct);
+ Geom::OptIntRect area = r.upgrade_2geom();
+ if (!area) return;
+ Inkscape::DrawingContext ct(surface, area->min());
+ ca->drawing.update(Geom::IntRect::infinite(), ca->ctx);
+ ca->drawing.render(ct, *area);
}
-
/*
Local Variables:
mode:c++
diff --git a/src/display/canvas-arena.h b/src/display/canvas-arena.h
index 220976da0..f145a9c70 100644
--- a/src/display/canvas-arena.h
+++ b/src/display/canvas-arena.h
@@ -15,9 +15,11 @@
#include <cairo.h>
#include <2geom/rect.h>
+#include "display/display-forward.h"
+#include "display/drawing.h"
+#include "display/drawing-item.h"
#include "display/sp-canvas.h"
#include "display/sp-canvas-item.h"
-#include "display/nr-arena-item.h"
G_BEGIN_DECLS
@@ -29,6 +31,7 @@ G_BEGIN_DECLS
typedef struct _SPCanvasArena SPCanvasArena;
typedef struct _SPCanvasArenaClass SPCanvasArenaClass;
+struct CachePrefObserver;
struct _SPCanvasArena {
SPCanvasItem item;
@@ -37,24 +40,20 @@ struct _SPCanvasArena {
guint sticky : 1;
Geom::Point c; // what is this?
- NRArena *arena;
- NRArenaItem *root;
- NRGC gc;
+ Inkscape::Drawing drawing;
+ Inkscape::UpdateContext ctx;
- NRArenaItem *active;
+ Inkscape::DrawingItem *active;
/* fixme: */
- NRArenaItem *picked;
- gdouble delta;
-
- Geom::IntRect cache_area;
- cairo_surface_t *cache;
- cairo_region_t *dirty;
+ Inkscape::DrawingItem *picked;
+ CachePrefObserver *observer;
+ double delta;
};
struct _SPCanvasArenaClass {
SPCanvasItemClass parent_class;
- gint (* arena_event) (SPCanvasArena *carena, NRArenaItem *item, GdkEvent *event);
+ gint (* arena_event) (SPCanvasArena *carena, Inkscape::DrawingItem *item, GdkEvent *event);
};
GType sp_canvas_arena_get_type (void);
diff --git a/src/display/display-forward.h b/src/display/display-forward.h
index bc7013214..7dccb76ef 100644
--- a/src/display/display-forward.h
+++ b/src/display/display-forward.h
@@ -10,12 +10,30 @@ typedef struct _SPCanvasItemClass SPCanvasItemClass;
struct SPCanvasGroup;
struct SPCanvasGroupClass;
class SPCurve;
+typedef struct _SPCanvasArena SPCanvasArena;
namespace Inkscape {
+class Drawing;
+class DrawingItem;
+class DrawingGroup;
+class DrawingImage;
+class DrawingShape;
+class DrawingGlyphs;
+class DrawingText;
+class UpdateContext;
+
+class DrawingContext;
+class DrawingSurface;
+class DrawingCache;
+
namespace Display {
class TemporaryItem;
class TemporaryItemList;
}
+
+namespace Filters {
+ class Filter;
+}
}
#endif /* !SEEN_DISPLAY_DISPLAY_FORWARD_H */
diff --git a/src/display/drawing-context.cpp b/src/display/drawing-context.cpp
new file mode 100644
index 000000000..3c0c2163b
--- /dev/null
+++ b/src/display/drawing-context.cpp
@@ -0,0 +1,152 @@
+/**
+ * @file
+ * @brief Cairo drawing context with Inkscape extensions
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2011 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "display/drawing-context.h"
+#include "display/drawing-surface.h"
+#include "display/cairo-utils.h"
+#include "helper/geom.h"
+
+namespace Inkscape {
+
+using Geom::X;
+using Geom::Y;
+
+/** @class DrawingContext::Save
+ * @brief RAII idiom for saving the state of DrawingContext. */
+
+DrawingContext::Save::Save()
+ : _ct(NULL)
+{}
+DrawingContext::Save::Save(DrawingContext &ct)
+ : _ct(&ct)
+{
+ _ct->save();
+}
+DrawingContext::Save::~Save()
+{
+ if (_ct) {
+ _ct->restore();
+ }
+}
+void DrawingContext::Save::save(DrawingContext &ct)
+{
+ if (_ct) {
+ // TODO: it might be better to treat this occurence as a bug
+ _ct->restore();
+ }
+ _ct = &ct;
+ _ct->save();
+}
+
+/** @class DrawingContext
+ * @brief Minimal wrapper over Cairo.
+ *
+ * This is a wrapper over cairo_t, extended with operations that work
+ * with 2Geom geometrical primitives. Some of this is probably duplicated
+ * in cairo-render-context.cpp, which provides higher level operations
+ * for drawing entire SPObjects when exporting.
+ */
+
+DrawingContext::DrawingContext(cairo_t *ct, Geom::Point const &origin)
+ : _ct(ct)
+ , _surface(new DrawingSurface(cairo_get_group_target(ct), origin))
+ , _delete_surface(true)
+ , _restore_context(true)
+{
+ _surface->_has_context = true;
+ cairo_reference(_ct);
+ cairo_save(_ct);
+ cairo_translate(_ct, -origin[Geom::X], -origin[Geom::Y]);
+}
+
+DrawingContext::DrawingContext(cairo_surface_t *surface, Geom::Point const &origin)
+ : _ct(NULL)
+ , _surface(new DrawingSurface(surface, origin))
+ , _delete_surface(true)
+ , _restore_context(false)
+{
+ _surface->_has_context = true;
+ _ct = _surface->createRawContext();
+}
+
+DrawingContext::DrawingContext(DrawingSurface &s)
+ : _ct(s.createRawContext())
+ , _surface(&s)
+ , _delete_surface(false)
+ , _restore_context(false)
+{}
+
+DrawingContext::~DrawingContext()
+{
+ if (_restore_context) {
+ cairo_restore(_ct);
+ }
+ cairo_destroy(_ct);
+ _surface->_has_context = false;
+ if (_delete_surface) {
+ delete _surface;
+ }
+}
+
+void DrawingContext::arc(Geom::Point const &center, double radius, Geom::AngleInterval const &angle)
+{
+ double from = angle.initialAngle();
+ double to = angle.finalAngle();
+ if (to > from) {
+ cairo_arc(_ct, center[X], center[Y], radius, from, to);
+ } else {
+ cairo_arc_negative(_ct, center[X], center[Y], radius, to, from);
+ }
+}
+
+void DrawingContext::transform(Geom::Affine const &trans) {
+ ink_cairo_transform(_ct, trans);
+}
+
+void DrawingContext::path(Geom::PathVector const &pv) {
+ feed_pathvector_to_cairo(_ct, pv);
+}
+
+void DrawingContext::paint(double alpha) {
+ if (alpha == 1.0) cairo_paint(_ct);
+ else cairo_paint_with_alpha(_ct, alpha);
+}
+void DrawingContext::setSource(guint32 rgba) {
+ ink_cairo_set_source_rgba32(_ct, rgba);
+}
+void DrawingContext::setSource(DrawingSurface *s) {
+ Geom::Point origin = s->origin();
+ cairo_set_source_surface(_ct, s->raw(), origin[X], origin[Y]);
+}
+void DrawingContext::setSourceCheckerboard() {
+ cairo_pattern_t *check = ink_cairo_pattern_create_checkerboard();
+ cairo_set_source(_ct, check);
+ cairo_pattern_destroy(check);
+}
+
+Geom::Rect DrawingContext::targetLogicalBounds() const
+{
+ Geom::Rect ret(_surface->area());
+ return ret;
+}
+
+} // end namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/drawing-context.h b/src/display/drawing-context.h
new file mode 100644
index 000000000..4ada79057
--- /dev/null
+++ b/src/display/drawing-context.h
@@ -0,0 +1,128 @@
+/**
+ * @file
+ * @brief Cairo drawing context with Inkscape extensions
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2011 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_INKSCAPE_DISPLAY_DRAWING_CONTEXT_H
+#define SEEN_INKSCAPE_DISPLAY_DRAWING_CONTEXT_H
+
+#include <boost/utility.hpp>
+#include <glib.h>
+#include <cairo.h>
+#include <2geom/affine.h>
+#include <2geom/angle.h>
+#include <2geom/rect.h>
+#include <2geom/transforms.h>
+
+namespace Inkscape {
+
+class DrawingSurface;
+
+class DrawingContext
+ : boost::noncopyable
+{
+public:
+ class Save {
+ public:
+ Save();
+ Save(DrawingContext &ct);
+ ~Save();
+ void save(DrawingContext &ct);
+ private:
+ DrawingContext *_ct;
+ };
+
+ DrawingContext(cairo_t *ct, Geom::Point const &origin);
+ DrawingContext(cairo_surface_t *surface, Geom::Point const &origin);
+ DrawingContext(DrawingSurface &s);
+ ~DrawingContext();
+
+ void save() { cairo_save(_ct); }
+ void restore() { cairo_restore(_ct); }
+ void pushGroup() { cairo_push_group(_ct); }
+ void pushAlphaGroup() { cairo_push_group_with_content(_ct, CAIRO_CONTENT_ALPHA); }
+ void popGroupToSource() { cairo_pop_group_to_source(_ct); }
+
+ void transform(Geom::Affine const &trans);
+ void translate(Geom::Point const &t) { cairo_translate(_ct, t[Geom::X], t[Geom::Y]); } // todo: take Translate
+ void translate(double dx, double dy) { cairo_translate(_ct, dx, dy); }
+ void scale(Geom::Scale const &s) { cairo_scale(_ct, s[Geom::X], s[Geom::Y]); }
+ void scale(double sx, double sy) { cairo_scale(_ct, sx, sy); }
+
+ void moveTo(Geom::Point const &p) { cairo_move_to(_ct, p[Geom::X], p[Geom::Y]); }
+ void lineTo(Geom::Point const &p) { cairo_line_to(_ct, p[Geom::X], p[Geom::Y]); }
+ void curveTo(Geom::Point const &p1, Geom::Point const &p2, Geom::Point const &p3) {
+ cairo_curve_to(_ct, p1[Geom::X], p1[Geom::Y], p2[Geom::X], p2[Geom::Y], p3[Geom::X], p3[Geom::Y]);
+ }
+ void arc(Geom::Point const &center, double radius, Geom::AngleInterval const &angle);
+ void rectangle(Geom::Rect const &r) {
+ cairo_rectangle(_ct, r.left(), r.top(), r.width(), r.height());
+ }
+ void rectangle(Geom::IntRect const &r) {
+ cairo_rectangle(_ct, r.left(), r.top(), r.width(), r.height());
+ }
+ void newPath() { cairo_new_path(_ct); }
+ void newSubpath() { cairo_new_sub_path(_ct); }
+ void path(Geom::PathVector const &pv);
+
+ void paint(double alpha = 1.0);
+ void fill() { cairo_fill(_ct); }
+ void fillPreserve() { cairo_fill_preserve(_ct); }
+ void stroke() { cairo_stroke(_ct); }
+ void strokePreserve() { cairo_stroke_preserve(_ct); }
+ void clip() { cairo_clip(_ct); }
+
+ void setLineWidth(double w) { cairo_set_line_width(_ct, w); }
+ void setLineCap(cairo_line_cap_t cap) { cairo_set_line_cap(_ct, cap); }
+ void setLineJoin(cairo_line_join_t join) { cairo_set_line_join(_ct, join); }
+ void setMiterLimit(double miter) { cairo_set_miter_limit(_ct, miter); }
+ void setFillRule(cairo_fill_rule_t rule) { cairo_set_fill_rule(_ct, rule); }
+ void setOperator(cairo_operator_t op) { cairo_set_operator(_ct, op); }
+ void setTolerance(double tol) { cairo_set_tolerance(_ct, tol); }
+ void setSource(cairo_pattern_t *source) { cairo_set_source(_ct, source); }
+ void setSource(cairo_surface_t *surface, double x, double y) {
+ cairo_set_source_surface(_ct, surface, x, y);
+ }
+ void setSource(double r, double g, double b, double a = 1.0) {
+ cairo_set_source_rgba(_ct, r, g, b, a);
+ }
+ void setSource(guint32 rgba);
+ void setSource(DrawingSurface *s);
+ void setSourceCheckerboard();
+
+ Geom::Rect targetLogicalBounds() const;
+
+ cairo_t *raw() { return _ct; }
+ cairo_surface_t *rawTarget() { return cairo_get_group_target(_ct); }
+
+private:
+ DrawingContext(cairo_t *ct, DrawingSurface *surface, bool destroy);
+
+ cairo_t *_ct;
+ DrawingSurface *_surface;
+ bool _delete_surface;
+ bool _restore_context;
+
+ friend class DrawingSurface;
+};
+
+} // end namespace Inkscape
+
+#endif // !SEEN_INKSCAPE_DISPLAY_DRAWING_ITEM_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/drawing-group.cpp b/src/display/drawing-group.cpp
new file mode 100644
index 000000000..a678c3feb
--- /dev/null
+++ b/src/display/drawing-group.cpp
@@ -0,0 +1,165 @@
+/**
+ * @file
+ * @brief Group belonging to an SVG drawing element
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2011 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "display/cairo-utils.h"
+#include "display/drawing.h"
+#include "display/drawing-context.h"
+#include "display/drawing-item.h"
+#include "display/drawing-group.h"
+#include "libnr/nr-values.h"
+#include "style.h"
+
+namespace Inkscape {
+
+DrawingGroup::DrawingGroup(Drawing &drawing)
+ : DrawingItem(drawing)
+ , _style(NULL)
+ , _child_transform(NULL)
+{}
+
+DrawingGroup::~DrawingGroup()
+{
+ if (_style)
+ sp_style_unref(_style);
+}
+
+/** @brief Set whether the group returns children from pick calls.
+ * Previously this feature was called "transparent groups".
+ */
+void
+DrawingGroup::setPickChildren(bool p)
+{
+ _pick_children = p;
+}
+
+void
+DrawingGroup::setStyle(SPStyle *style)
+{
+ _setStyleCommon(_style, style);
+}
+
+/** @brief Set additional transform for the group.
+ * This is applied after the normal transform and mainly useful for
+ * markers, clipping paths, etc.
+ */
+void
+DrawingGroup::setChildTransform(Geom::Affine const &new_trans)
+{
+ Geom::Affine current;
+ if (_child_transform) {
+ current = *_child_transform;
+ }
+
+ if (!Geom::are_near(current, new_trans, NR_EPSILON)) {
+ // mark the area where the object was for redraw.
+ _markForRendering();
+ if (new_trans.isIdentity()) {
+ delete _child_transform; // delete NULL; is safe
+ _child_transform = NULL;
+ } else {
+ _child_transform = new Geom::Affine(new_trans);
+ }
+ _markForUpdate(STATE_ALL, true);
+ }
+}
+
+unsigned
+DrawingGroup::_updateItem(Geom::IntRect const &area, UpdateContext const &ctx, unsigned flags, unsigned reset)
+{
+ unsigned beststate = STATE_ALL;
+ bool outline = _drawing.outline();
+
+ UpdateContext child_ctx(ctx);
+ if (_child_transform) {
+ child_ctx.ctm = *_child_transform * ctx.ctm;
+ }
+ for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
+ i->update(area, child_ctx, flags, reset);
+ }
+ if (beststate & STATE_BBOX) {
+ _bbox = Geom::OptIntRect();
+ for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
+ if (i->visible()) {
+ _bbox.unionWith(outline ? i->geometricBounds() : i->visualBounds());
+ }
+ }
+ }
+ return beststate;
+}
+
+unsigned
+DrawingGroup::_renderItem(DrawingContext &ct, Geom::IntRect const &area, unsigned flags, DrawingItem *stop_at)
+{
+ if (stop_at == NULL) {
+ // normal rendering
+ for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
+ i->render(ct, area, flags, stop_at);
+ }
+ } else {
+ // background rendering
+ for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
+ if (&*i == stop_at) return RENDER_OK; // do not render the stop_at item at all
+ if (i->isAncestorOf(stop_at)) {
+ // render its ancestors without masks, opacity or filters
+ i->render(ct, area, flags | RENDER_FILTER_BACKGROUND, stop_at);
+ // stop further rendering
+ return RENDER_OK;
+ } else {
+ i->render(ct, area, flags, stop_at);
+ }
+ }
+ }
+ return RENDER_OK;
+}
+
+void
+DrawingGroup::_clipItem(DrawingContext &ct, Geom::IntRect const &area)
+{
+ for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
+ i->clip(ct, area);
+ }
+}
+
+DrawingItem *
+DrawingGroup::_pickItem(Geom::Point const &p, double delta, unsigned flags)
+{
+ for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
+ DrawingItem *picked = i->pick(p, delta, flags);
+ if (picked) {
+ return _pick_children ? picked : this;
+ }
+ }
+ return NULL;
+}
+
+bool
+DrawingGroup::_canClip()
+{
+ return true;
+}
+
+bool is_drawing_group(DrawingItem *item)
+{
+ return dynamic_cast<DrawingGroup *>(item) != NULL;
+}
+
+} // end namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/drawing-group.h b/src/display/drawing-group.h
new file mode 100644
index 000000000..961e5b9a3
--- /dev/null
+++ b/src/display/drawing-group.h
@@ -0,0 +1,62 @@
+/**
+ * @file
+ * @brief Group belonging to an SVG drawing element
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2011 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_INKSCAPE_DISPLAY_DRAWING_GROUP_H
+#define SEEN_INKSCAPE_DISPLAY_DRAWING_GROUP_H
+
+#include "display/drawing-item.h"
+
+class SPStyle;
+
+namespace Inkscape {
+
+class DrawingGroup
+ : public DrawingItem
+{
+public:
+ DrawingGroup(Drawing &drawing);
+ ~DrawingGroup();
+
+ bool pickChildren() { return _pick_children; }
+ void setPickChildren(bool p);
+
+ void setStyle(SPStyle *style);
+ void setChildTransform(Geom::Affine const &new_trans);
+
+protected:
+ virtual unsigned _updateItem(Geom::IntRect const &area, UpdateContext const &ctx,
+ unsigned flags, unsigned reset);
+ virtual unsigned _renderItem(DrawingContext &ct, Geom::IntRect const &area, unsigned flags,
+ DrawingItem *stop_at);
+ virtual void _clipItem(DrawingContext &ct, Geom::IntRect const &area);
+ virtual DrawingItem *_pickItem(Geom::Point const &p, double delta, unsigned flags);
+ virtual bool _canClip();
+
+ SPStyle *_style;
+ Geom::Affine *_child_transform;
+};
+
+bool is_drawing_group(DrawingItem *item);
+
+} // end namespace Inkscape
+
+#endif // !SEEN_INKSCAPE_DISPLAY_DRAWING_ITEM_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/drawing-image.cpp b/src/display/drawing-image.cpp
new file mode 100644
index 000000000..fa0402699
--- /dev/null
+++ b/src/display/drawing-image.cpp
@@ -0,0 +1,264 @@
+/**
+ * @file
+ * @brief Bitmap image belonging to an SVG drawing
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2011 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "display/cairo-utils.h"
+#include "display/drawing.h"
+#include "display/drawing-context.h"
+#include "display/drawing-image.h"
+#include "preferences.h"
+#include "style.h"
+
+namespace Inkscape {
+
+DrawingImage::DrawingImage(Drawing &drawing)
+ : DrawingItem(drawing)
+ , _pixbuf(NULL)
+ , _surface(NULL)
+ , _style(NULL)
+{}
+
+DrawingImage::~DrawingImage()
+{
+ if (_style)
+ sp_style_unref(_style);
+ if (_pixbuf) {
+ cairo_surface_destroy(_surface);
+ g_object_unref(_pixbuf);
+ }
+}
+
+void
+DrawingImage::setARGB32Pixbuf(GdkPixbuf *pb)
+{
+ // when done in this order, it won't break if pb == image->pixbuf and the refcount is 1
+ if (pb != NULL) {
+ g_object_ref (pb);
+ }
+ if (_pixbuf != NULL) {
+ g_object_unref(_pixbuf);
+ cairo_surface_destroy(_surface);
+ }
+ _pixbuf = pb;
+ _surface = pb ? ink_cairo_surface_create_for_argb32_pixbuf(pb) : NULL;
+
+ _markForUpdate(STATE_ALL, false);
+}
+
+void
+DrawingImage::setStyle(SPStyle *style)
+{
+ _setStyleCommon(_style, style);
+}
+
+void
+DrawingImage::setScale(double sx, double sy)
+{
+ _scale = Geom::Scale(sx, sy);
+ _markForUpdate(STATE_ALL, false);
+}
+
+void
+DrawingImage::setOrigin(Geom::Point const &o)
+{
+ _origin = o;
+ _markForUpdate(STATE_ALL, false);
+}
+
+void
+DrawingImage::setClipbox(Geom::Rect const &box)
+{
+ _clipbox = box;
+ _markForUpdate(STATE_ALL, false);
+}
+
+Geom::Rect
+DrawingImage::bounds() const
+{
+ if (!_pixbuf) return _clipbox;
+
+ double pw = gdk_pixbuf_get_width(_pixbuf);
+ double ph = gdk_pixbuf_get_height(_pixbuf);
+ double vw = pw * _scale[Geom::X];
+ double vh = ph * _scale[Geom::Y];
+ Geom::Point wh(vw, vh);
+ Geom::Rect view(_origin, _origin+wh);
+ Geom::OptRect res = _clipbox & view;
+ Geom::Rect ret = res ? *res : _clipbox;
+
+ return ret;
+}
+
+unsigned
+DrawingImage::_updateItem(Geom::IntRect const &, UpdateContext const &, unsigned, unsigned)
+{
+ _markForRendering();
+
+ // Calculate bbox
+ if (_pixbuf) {
+ Geom::Rect r = bounds() * _ctm;
+ _bbox = r.roundOutwards();
+ } else {
+ _bbox = Geom::OptIntRect();
+ }
+
+ return STATE_ALL;
+}
+
+unsigned
+DrawingImage::_renderItem(DrawingContext &ct, Geom::IntRect const &area, unsigned flags, DrawingItem *stop_at)
+{
+ bool outline = _drawing.outline();
+
+ if (!outline) {
+ if (!_pixbuf) return RENDER_OK;
+
+ Inkscape::DrawingContext::Save save(ct);
+ ct.transform(_ctm);
+ ct.newPath();
+ ct.rectangle(_clipbox);
+ ct.clip();
+
+ ct.translate(_origin);
+ ct.scale(_scale);
+ ct.setSource(_surface, 0, 0);
+
+ cairo_matrix_t tt;
+ Geom::Affine total;
+ cairo_get_matrix(ct.raw(), &tt);
+ ink_matrix_to_2geom(total, tt);
+
+ if (total.expansionX() > 1.0 || total.expansionY() > 1.0) {
+ cairo_pattern_t *p = cairo_get_source(ct.raw());
+ cairo_pattern_set_filter(p, CAIRO_FILTER_NEAREST);
+ }
+ //ct.paint(_opacity);
+ ct.paint();
+
+ } else { // outline; draw a rect instead
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ guint32 rgba = prefs->getInt("/options/wireframecolors/images", 0xff0000ff);
+
+ { Inkscape::DrawingContext::Save save(ct);
+ ct.transform(_ctm);
+ ct.newPath();
+
+ Geom::Rect r = bounds();
+ Geom::Point c00 = r.corner(0);
+ Geom::Point c01 = r.corner(3);
+ Geom::Point c11 = r.corner(2);
+ Geom::Point c10 = r.corner(1);
+
+ ct.moveTo(c00);
+ // the box
+ ct.lineTo(c10);
+ ct.lineTo(c11);
+ ct.lineTo(c01);
+ ct.lineTo(c00);
+ // the diagonals
+ ct.lineTo(c11);
+ ct.moveTo(c10);
+ ct.lineTo(c01);
+ }
+
+ ct.setLineWidth(0.5);
+ ct.setSource(rgba);
+ ct.stroke();
+ }
+ return RENDER_OK;
+}
+
+/** Calculates the closest distance from p to the segment a1-a2*/
+static double
+distance_to_segment (Geom::Point const &p, Geom::Point const &a1, Geom::Point const &a2)
+{
+ // calculate sides of the triangle and their squares
+ double d1 = Geom::L2(p - a1);
+ double d1_2 = d1 * d1;
+ double d2 = Geom::L2(p - a2);
+ double d2_2 = d2 * d2;
+ double a = Geom::L2(a1 - a2);
+ double a_2 = a * a;
+
+ // if one of the angles at the base is > 90, return the corresponding side
+ if (d1_2 + a_2 <= d2_2) return d1;
+ if (d2_2 + a_2 <= d1_2) return d2;
+
+ // otherwise calculate the height to the base
+ double peri = (a + d1 + d2)/2;
+ return (2*sqrt(peri * (peri - a) * (peri - d1) * (peri - d2))/a);
+}
+
+DrawingItem *
+DrawingImage::_pickItem(Geom::Point const &p, double delta, unsigned /*sticky*/)
+{
+ if (!_pixbuf) return NULL;
+
+ bool outline = _drawing.outline();
+
+ if (outline) {
+ Geom::Rect r = bounds();
+
+ Geom::Point c00 = r.corner(0);
+ Geom::Point c01 = r.corner(3);
+ Geom::Point c11 = r.corner(2);
+ Geom::Point c10 = r.corner(1);
+
+ // frame
+ if (distance_to_segment (p, c00, c10) < delta) return this;
+ if (distance_to_segment (p, c10, c11) < delta) return this;
+ if (distance_to_segment (p, c11, c01) < delta) return this;
+ if (distance_to_segment (p, c01, c00) < delta) return this;
+
+ // diagonals
+ if (distance_to_segment (p, c00, c11) < delta) return this;
+ if (distance_to_segment (p, c10, c01) < delta) return this;
+
+ return NULL;
+
+ } else {
+ unsigned char *const pixels = gdk_pixbuf_get_pixels(_pixbuf);
+ int width = gdk_pixbuf_get_width(_pixbuf);
+ int height = gdk_pixbuf_get_height(_pixbuf);
+ int rowstride = gdk_pixbuf_get_rowstride(_pixbuf);
+
+ Geom::Point tp = p * _ctm.inverse();
+ Geom::Rect r = bounds();
+
+ if (!r.contains(tp))
+ return NULL;
+
+ double vw = width * _scale[Geom::X];
+ double vh = height * _scale[Geom::Y];
+ int ix = floor((tp[Geom::X] - _origin[Geom::X]) / vw * width);
+ int iy = floor((tp[Geom::Y] - _origin[Geom::Y]) / vh * height);
+
+ if ((ix < 0) || (iy < 0) || (ix >= width) || (iy >= height))
+ return NULL;
+
+ unsigned char *pix_ptr = pixels + iy * rowstride + ix * 4;
+ // pick if the image is less than 99% transparent
+ float alpha = (pix_ptr[3] / 255.0f) * _opacity;
+ return alpha > 0.01 ? this : NULL;
+ }
+}
+
+} // end namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/drawing-image.h b/src/display/drawing-image.h
new file mode 100644
index 000000000..300d6f0b5
--- /dev/null
+++ b/src/display/drawing-image.h
@@ -0,0 +1,67 @@
+/**
+ * @file
+ * @brief Bitmap image belonging to an SVG drawing
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2011 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_INKSCAPE_DISPLAY_DRAWING_IMAGE_H
+#define SEEN_INKSCAPE_DISPLAY_DRAWING_IMAGE_H
+
+#include <cairo.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <2geom/transforms.h>
+
+#include "display/drawing-item.h"
+
+namespace Inkscape {
+
+class DrawingImage
+ : public DrawingItem
+{
+public:
+ DrawingImage(Drawing &drawing);
+ ~DrawingImage();
+
+ void setARGB32Pixbuf(GdkPixbuf *pb);
+ void setStyle(SPStyle *style);
+ void setScale(double sx, double sy);
+ void setOrigin(Geom::Point const &o);
+ void setClipbox(Geom::Rect const &box);
+ Geom::Rect bounds() const;
+
+protected:
+ virtual unsigned _updateItem(Geom::IntRect const &area, UpdateContext const &ctx,
+ unsigned flags, unsigned reset);
+ virtual unsigned _renderItem(DrawingContext &ct, Geom::IntRect const &area, unsigned flags,
+ DrawingItem *stop_at);
+ virtual DrawingItem *_pickItem(Geom::Point const &p, double delta, unsigned flags);
+
+ GdkPixbuf *_pixbuf;
+ cairo_surface_t *_surface;
+ SPStyle *_style;
+
+ // TODO: the following three should probably be merged into a new Geom::Viewbox object
+ Geom::Rect _clipbox; ///< for preserveAspectRatio
+ Geom::Point _origin;
+ Geom::Scale _scale;
+};
+
+} // end namespace Inkscape
+
+#endif // !SEEN_INKSCAPE_DISPLAY_DRAWING_ITEM_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/drawing-item.cpp b/src/display/drawing-item.cpp
new file mode 100644
index 000000000..a5496e999
--- /dev/null
+++ b/src/display/drawing-item.cpp
@@ -0,0 +1,900 @@
+/**
+ * @file
+ * @brief Canvas item belonging to an SVG drawing element
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2011 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <climits>
+#include "display/cairo-utils.h"
+#include "display/cairo-templates.h"
+#include "display/drawing.h"
+#include "display/drawing-context.h"
+#include "display/drawing-item.h"
+#include "display/drawing-group.h"
+#include "display/drawing-surface.h"
+#include "nr-filter.h"
+#include "preferences.h"
+#include "style.h"
+
+namespace Inkscape {
+
+/** @class DrawingItem
+ * @brief SVG drawing item for display.
+ *
+ * This was previously known as NRArenaItem. It represents the renderable
+ * portion of the SVG document. Typically this is created by the SP tree,
+ * in particular the show() virtual function.
+ *
+ * @section ObjectLifetime Object lifetime
+ * Deleting a DrawingItem will cause all of its children to be deleted as well.
+ * This can lead to nasty surprises if you hold references to things
+ * which are children of what is being deleted. Therefore, in the SP tree,
+ * you always need to delete the item views of children before deleting
+ * the view of the parent. Do not call delete on things returned from show()
+ * - this will cause dangling pointers inside the SPItem and lead to a crash.
+ * Use the corresponing hide() method.
+ *
+ * Outside of the SP tree, you should not use any references after the root node
+ * has been deleted.
+ */
+
+DrawingItem::DrawingItem(Drawing &drawing)
+ : _drawing(drawing)
+ , _parent(NULL)
+ , _key(0)
+ , _opacity(1.0)
+ , _transform(NULL)
+ , _clip(NULL)
+ , _mask(NULL)
+ , _filter(NULL)
+ , _user_data(NULL)
+ , _cache(NULL)
+ , _state(0)
+ , _child_type(CHILD_ORPHAN)
+ , _background_new(0)
+ , _background_accumulate(0)
+ , _visible(true)
+ , _sensitive(true)
+ , _cached(0)
+ , _cached_persistent(0)
+ , _has_cache_iterator(0)
+ , _propagate(0)
+// , _renders_opacity(0)
+ , _pick_children(0)
+{}
+
+DrawingItem::~DrawingItem()
+{
+ _drawing.signal_item_deleted.emit(this);
+ //if (!_children.empty()) {
+ // g_warning("Removing item with children");
+ //}
+
+ // remove from the set of cached items and delete cache
+ setCached(false, true);
+ if (_has_cache_iterator) {
+ _drawing._candidate_items.erase(_cache_iterator);
+ }
+ // remove this item from parent's children list
+ // due to the effect of clearChildren(), this only happens for the top-level deleted item
+ if (_parent) {
+ _markForRendering();
+ }
+
+ switch (_child_type) {
+ case CHILD_NORMAL: {
+ ChildrenList::iterator ithis = _parent->_children.iterator_to(*this);
+ _parent->_children.erase(ithis);
+ } break;
+ case CHILD_CLIP:
+ // we cannot call setClip(NULL) or setMask(NULL),
+ // because that would be an endless loop
+ _parent->_clip = NULL;
+ break;
+ case CHILD_MASK:
+ _parent->_mask = NULL;
+ break;
+ case CHILD_ROOT:
+ _drawing._root = NULL;
+ break;
+ default: ;
+ }
+
+ if (_parent) {
+ _parent->_markForUpdate(STATE_ALL, false);
+ }
+ clearChildren();
+ delete _transform;
+ delete _clip;
+ delete _mask;
+ delete _filter;
+}
+
+DrawingItem *
+DrawingItem::parent() const
+{
+ // initially I wanted to return NULL if we are a clip or mask child,
+ // but the previous behavior was just to return the parent regardless of child type
+ return _parent;
+}
+
+/// Returns true if item is among the descendants. Will return false if item == this.
+bool
+DrawingItem::isAncestorOf(DrawingItem *item) const
+{
+ for (DrawingItem *i = item->_parent; i; i = i->_parent) {
+ if (i == this) return true;
+ }
+ return false;
+}
+
+void
+DrawingItem::appendChild(DrawingItem *item)
+{
+ item->_parent = this;
+ assert(item->_child_type == CHILD_ORPHAN);
+ item->_child_type = CHILD_NORMAL;
+ _children.push_back(*item);
+ _markForUpdate(STATE_ALL, false);
+}
+
+void
+DrawingItem::prependChild(DrawingItem *item)
+{
+ item->_parent = this;
+ assert(item->_child_type == CHILD_ORPHAN);
+ item->_child_type = CHILD_NORMAL;
+ _children.push_front(*item);
+ _markForUpdate(STATE_ALL, false);
+}
+
+/// Delete all regular children of this item (not mask or clip).
+void
+DrawingItem::clearChildren()
+{
+ // prevent children from referencing the parent during deletion
+ // this way, children won't try to remove themselves from a list
+ // from which they have already been removed by clear_and_dispose
+ for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
+ i->_parent = NULL;
+ i->_child_type = CHILD_ORPHAN;
+ }
+ _children.clear_and_dispose(DeleteDisposer());
+}
+
+/// Set the incremental transform for this item
+void
+DrawingItem::setTransform(Geom::Affine const &new_trans)
+{
+ Geom::Affine current;
+ if (_transform) {
+ current = *_transform;
+ }
+
+ if (!Geom::are_near(current, new_trans, NR_EPSILON)) {
+ // mark the area where the object was for redraw.
+ _markForRendering();
+ if (new_trans.isIdentity()) {
+ delete _transform; // delete NULL; is safe
+ _transform = NULL;
+ } else {
+ _transform = new Geom::Affine(new_trans);
+ }
+ _markForUpdate(STATE_ALL, true);
+ }
+}
+
+void
+DrawingItem::setOpacity(float opacity)
+{
+ _opacity = opacity;
+ _markForRendering();
+}
+
+void
+DrawingItem::setVisible(bool v)
+{
+ _visible = v;
+ _markForRendering();
+}
+
+/// This is currently unused
+void
+DrawingItem::setSensitive(bool s)
+{
+ _sensitive = s;
+}
+
+/** @brief Enable / disable storing the rendering in memory.
+ * Calling setCached(false, true) will also remove the persistent status
+ */
+void
+DrawingItem::setCached(bool cached, bool persistent)
+{
+ static const char *cache_env = getenv("_INKSCAPE_DISABLE_CACHE");
+ if (cache_env) return;
+
+ if (_cached_persistent && !persistent)
+ return;
+
+ _cached = cached;
+ _cached_persistent = persistent ? cached : false;
+ if (cached) {
+ _drawing._cached_items.insert(this);
+ } else {
+ _drawing._cached_items.erase(this);
+ delete _cache;
+ _cache = NULL;
+ }
+}
+
+void
+DrawingItem::setClip(DrawingItem *item)
+{
+ _markForRendering();
+ delete _clip;
+ _clip = item;
+ if (item) {
+ item->_parent = this;
+ assert(item->_child_type == CHILD_ORPHAN);
+ item->_child_type = CHILD_CLIP;
+ }
+ _markForUpdate(STATE_ALL, true);
+}
+
+void
+DrawingItem::setMask(DrawingItem *item)
+{
+ _markForRendering();
+ delete _mask;
+ _mask = item;
+ if (item) {
+ item->_parent = this;
+ assert(item->_child_type == CHILD_ORPHAN);
+ item->_child_type = CHILD_MASK;
+ }
+ _markForUpdate(STATE_ALL, true);
+}
+
+/// Move this item to the given place in the Z order of siblings.
+/// Does nothing if the item has no parent.
+void
+DrawingItem::setZOrder(unsigned z)
+{
+ if (!_parent) return;
+
+ ChildrenList::iterator it = _parent->_children.iterator_to(*this);
+ _parent->_children.erase(it);
+
+ ChildrenList::iterator i = _parent->_children.begin();
+ std::advance(i, std::min(z, unsigned(_parent->_children.size())));
+ _parent->_children.insert(i, *this);
+ _markForRendering();
+}
+
+void
+DrawingItem::setItemBounds(Geom::OptRect const &bounds)
+{
+ _item_bbox = bounds;
+}
+
+/** @brief Update derived data before operations.
+ * The purpose of this call is to recompute internal data which depends
+ * on the attributes of the object, but is not directly settable by the user.
+ * Precomputing this data speeds up later rendering, because some items
+ * can be omitted.
+ *
+ * Currently this method handles updating the visual and geometric bounding boxes
+ * in pixels, storing the total transformation from item space to the screen
+ * and cache invalidation.
+ *
+ * @param area Area to which the update should be restricted. Only takes effect
+ * if the bounding box is known.
+ * @param ctx A structure to store cascading state.
+ * @param flags Which internal data should be recomputed. This can be any combination
+ * of StateFlags.
+ * @param reset State fields that should be reset before processing them. This is
+ * a means to force a recomputation of internal data even if the item
+ * considers it up to date. Mainly for internal use, such as
+ * propagating bunding box recomputation to children when the item's
+ * transform changes.
+ */
+void
+DrawingItem::update(Geom::IntRect const &area, UpdateContext const &ctx, unsigned flags, unsigned reset)
+{
+ bool render_filters = _drawing.renderFilters();
+ bool outline = _drawing.outline();
+
+ // Set reset flags according to propagation status
+ reset |= _propagate_state;
+ _propagate_state = 0;
+
+ _state &= ~reset; // reset state of this item
+
+ if ((~_state & flags) == 0) return; // nothing to do
+
+ // TODO this might be wrong
+ if (_state & STATE_BBOX) {
+ // we have up-to-date bbox
+ if (!area.intersects(outline ? _bbox : _drawbox)) return;
+ }
+
+ // compute which elements need an update
+ unsigned to_update = _state ^ flags;
+
+ // this needs to be called before we recurse into children
+ if (to_update & STATE_BACKGROUND) {
+ _background_accumulate = _background_new;
+ if (_child_type == CHILD_NORMAL && _parent->_background_accumulate)
+ _background_accumulate = true;
+ }
+
+ UpdateContext child_ctx(ctx);
+ if (_transform) {
+ child_ctx.ctm = *_transform * ctx.ctm;
+ }
+ /* Remember the transformation matrix */
+ Geom::Affine ctm_change = _ctm.inverse() * child_ctx.ctm;
+ _ctm = child_ctx.ctm;
+
+ // update _bbox and call this function for children
+ _state = _updateItem(area, child_ctx, flags, reset);
+
+ if (to_update & STATE_BBOX) {
+ // compute drawbox
+ if (_filter && render_filters) {
+ _drawbox = _filter->compute_drawbox(this, _item_bbox);
+ } else {
+ _drawbox = _bbox;
+ }
+
+ // Clipping
+ if (_clip) {
+ _clip->update(area, child_ctx, flags, reset);
+ if (outline) {
+ _bbox.unionWith(_clip->_bbox);
+ } else {
+ _drawbox.intersectWith(_clip->_bbox);
+ }
+ }
+ // Masking
+ if (_mask) {
+ _mask->update(area, child_ctx, flags, reset);
+ if (outline) {
+ _bbox.unionWith(_mask->_bbox);
+ } else {
+ // for masking, we need full drawbox of mask
+ _drawbox.intersectWith(_mask->_drawbox);
+ }
+ }
+ }
+
+ if (to_update & STATE_CACHE) {
+ // Update cache score for this item
+ if (_has_cache_iterator) {
+ // remove old score information
+ _drawing._candidate_items.erase(_cache_iterator);
+ _has_cache_iterator = false;
+ }
+ double score = _cacheScore();
+ if (score >= _drawing._cache_score_threshold) {
+ CacheRecord cr;
+ cr.score = score;
+ // if _cacheRect() is empty, a negative score will be returned from _cacheScore(),
+ // so this will not execute (cache score threshold must be positive)
+ cr.cache_size = _cacheRect()->area() * 4;
+ cr.item = this;
+ _drawing._candidate_items.push_front(cr);
+ _cache_iterator = _drawing._candidate_items.begin();
+ _has_cache_iterator = true;
+ }
+
+ /* Update cache if enabled.
+ * General note: here we only tell the cache how it has to transform
+ * during the render phase. The transformation is deferred because
+ * after the update the item can have its caching turned off,
+ * e.g. because its filter was removed. This way we avoid tempoerarily
+ * using more memory than the cache budget */
+ if (_cache) {
+ Geom::OptIntRect cl = _cacheRect();
+ if (_visible && cl) { // never create cache for invisible items
+ // this takes care of invalidation on transform
+ _cache->scheduleTransform(*cl, ctm_change);
+ } else {
+ // Destroy cache for this item - outside of canvas or invisible.
+ // The opposite transition (invisible -> visible or object
+ // entering the canvas) is handled during the render phase
+ delete _cache;
+ _cache = NULL;
+ }
+ }
+ }
+
+ if (to_update & STATE_RENDER) {
+ // now that we know drawbox, dirty the corresponding rect on canvas
+ // unless filtered, groups do not need to render by themselves, only their members
+ if (!is_drawing_group(this) || (_filter && render_filters)) {
+ _markForRendering();
+ }
+ }
+}
+
+struct MaskLuminanceToAlpha {
+ guint32 operator()(guint32 in) {
+ EXTRACT_ARGB32(in, a, r, g, b)
+ // the operation of unpremul -> luminance-to-alpha -> multiply by alpha
+ // is equivalent to luminance-to-alpha on premultiplied color values
+ // original computation in double: r*0.2125 + g*0.7154 + b*0.0721
+ guint32 ao = r*109 + g*366 + b*37; // coeffs add up to 512
+ return ((ao + 256) << 15) & 0xff000000; // equivalent to ((ao + 256) / 512) << 24
+ }
+};
+
+/** @brief Rasterize items.
+ * This method submits the drawing opeartions required to draw this item
+ * to the supplied DrawingContext, restricting drawing the the specified area.
+ *
+ * This method does some common tasks and calls the item-specific rendering
+ * function, _renderItem(), to render e.g. paths or bitmaps.
+ *
+ * @param flags Rendering options. This deals mainly with cache control.
+ */
+unsigned
+DrawingItem::render(DrawingContext &ct, Geom::IntRect const &area, unsigned flags, DrawingItem *stop_at)
+{
+ bool outline = _drawing.outline();
+ bool render_filters = _drawing.renderFilters();
+
+ // stop_at is handled in DrawingGroup, but this check is required to handle the case
+ // where a filtered item with background-accessing filter has enable-background: new
+ if (this == stop_at) return RENDER_STOP;
+
+ // If we are invisible, return immediately
+ if (!_visible) return RENDER_OK;
+ if (_ctm.isSingular(NR_EPSILON)) return RENDER_OK;
+
+ // TODO convert outline rendering to a separate virtual function
+ if (outline) {
+ _renderOutline(ct, area, flags);
+ return RENDER_OK;
+ }
+
+ // carea is the area to paint
+ Geom::OptIntRect carea = Geom::intersect(area, _drawbox);
+ if (!carea) return RENDER_OK;
+
+ // render from cache if possible
+ if (_cached) {
+ if (_cache) {
+ _cache->prepare();
+ _cache->paintFromCache(ct, carea);
+ if (!carea) return RENDER_OK;
+ } else {
+ // There is no cache. This could be because caching of this item
+ // was just turned on after the last update phase, or because
+ // we were previously outside of the canvas.
+ Geom::OptIntRect cl = _drawing.cacheLimit();
+ cl.intersectWith(_drawbox);
+ if (cl) {
+ _cache = new DrawingCache(*cl);
+ }
+ }
+ } else {
+ // if our caching was turned off after the last update, it was already
+ // deleted in setCached()
+ }
+
+ // determine whether this shape needs intermediate rendering.
+ bool needs_intermediate_rendering = false;
+ bool &nir = needs_intermediate_rendering;
+ bool needs_opacity = (_opacity < 0.995);
+
+ // this item needs an intermediate rendering if:
+ nir |= (_clip != NULL); // 1. it has a clipping path
+ nir |= (_mask != NULL); // 2. it has a mask
+ nir |= (_filter != NULL && render_filters); // 3. it has a filter
+ nir |= needs_opacity; // 4. it is non-opaque
+ nir |= (_cache != NULL); // 5. it is cached
+
+ /* How the rendering is done.
+ *
+ * Clipping, masking and opacity are done by rendering them to a surface
+ * and then compositing the object's rendering onto it with the IN operator.
+ * The object itself is rendered to a group.
+ *
+ * Opacity is done by rendering the clipping path with an alpha
+ * value corresponding to the opacity. If there is no clipping path,
+ * the entire intermediate surface is painted with alpha corresponding
+ * to the opacity value.
+ */
+
+ // Short-circuit the simple case.
+ // We also use this path for filter background rendering, because masking, clipping,
+ // filters and opacity do not apply when rendering the ancestors of the filtered
+ // element
+ if ((flags & RENDER_FILTER_BACKGROUND) || !needs_intermediate_rendering) {
+ return _renderItem(ct, *carea, flags & ~RENDER_FILTER_BACKGROUND, stop_at);
+ }
+
+ // iarea is the bounding box for intermediate rendering
+ // Note 1: Pixels inside iarea but outside carea are invalid
+ // (incomplete filter dependence region).
+ // Note 2: We only need to render carea of clip and mask, but
+ // iarea of the object.
+ Geom::OptIntRect iarea = carea;
+ // expand carea to contain the dependent area of filters.
+ if (_filter && render_filters) {
+ _filter->area_enlarge(*iarea, this);
+ iarea.intersectWith(_drawbox);
+ }
+
+ DrawingSurface intermediate(*iarea);
+ DrawingContext ict(intermediate);
+ unsigned render_result = RENDER_OK;
+
+ // 1. Render clipping path with alpha = opacity.
+ ict.setSource(0,0,0,_opacity);
+ // Since clip can be combined with opacity, the result could be incorrect
+ // for overlapping clip children. To fix this we use the SOURCE operator
+ // instead of the default OVER.
+ ict.setOperator(CAIRO_OPERATOR_SOURCE);
+ if (_clip) {
+ _clip->clip(ict, *carea); // fixme: carea or area?
+ } else {
+ // if there is no clipping path, fill the entire surface with alpha = opacity.
+ ict.paint();
+ }
+ ict.setOperator(CAIRO_OPERATOR_OVER); // reset back to default
+
+ // 2. Render the mask if present and compose it with the clipping path + opacity.
+ if (_mask) {
+ ict.pushGroup();
+ _mask->render(ict, *carea, flags);
+
+ cairo_surface_t *mask_s = ict.rawTarget();
+ // Convert mask's luminance to alpha
+ ink_cairo_surface_filter(mask_s, mask_s, MaskLuminanceToAlpha());
+ ict.popGroupToSource();
+ ict.setOperator(CAIRO_OPERATOR_IN);
+ ict.paint();
+ ict.setOperator(CAIRO_OPERATOR_OVER);
+ }
+
+ // 3. Render object itself
+ ict.pushGroup();
+ render_result = _renderItem(ict, *iarea, flags, stop_at);
+
+ // 4. Apply filter.
+ if (_filter && render_filters) {
+ bool rendered = false;
+ if (_filter->uses_background() && _background_accumulate) {
+ DrawingItem *bg_root = this;
+ for (; bg_root; bg_root = bg_root->_parent) {
+ if (bg_root->_background_new) break;
+ }
+ if (bg_root) {
+ DrawingSurface bg(*iarea);
+ DrawingContext bgct(bg);
+ bg_root->render(bgct, *iarea, flags | RENDER_FILTER_BACKGROUND, this);
+ _filter->render(this, ict, &bgct);
+ rendered = true;
+ }
+ }
+ if (!rendered) {
+ _filter->render(this, ict, NULL);
+ }
+ // Note that because the object was rendered to a group,
+ // the internals of the filter need to use cairo_get_group_target()
+ // instead of cairo_get_target().
+ }
+
+ // 5. Render object inside the composited mask + clip
+ ict.popGroupToSource();
+ ict.setOperator(CAIRO_OPERATOR_IN);
+ ict.paint();
+
+ // 6. Paint the completed rendering onto the base context (or into cache)
+ if (_cached && _cache) {
+ DrawingContext cachect(*_cache);
+ cachect.rectangle(*carea);
+ cachect.setOperator(CAIRO_OPERATOR_SOURCE);
+ cachect.setSource(&intermediate);
+ cachect.fill();
+ _cache->markClean(*carea);
+ }
+ ct.rectangle(*carea);
+ ct.setSource(&intermediate);
+ ct.fill();
+ ct.setSource(0,0,0,0);
+ // the call above is to clear a ref on the intermediate surface held by ct
+
+ return render_result;
+}
+
+void
+DrawingItem::_renderOutline(DrawingContext &ct, Geom::IntRect const &area, unsigned flags)
+{
+ // intersect with bbox rather than drawbox, as we want to render things outside
+ // of the clipping path as well
+ Geom::OptIntRect carea = Geom::intersect(area, _bbox);
+ if (!carea) return;
+
+ // just render everything: item, clip, mask
+ // First, render the object itself
+ _renderItem(ct, *carea, flags, NULL);
+
+ // render clip and mask, if any
+ guint32 saved_rgba = _drawing.outlinecolor; // save current outline color
+ // render clippath as an object, using a different color
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ if (_clip) {
+ _drawing.outlinecolor = prefs->getInt("/options/wireframecolors/clips", 0x00ff00ff); // green clips
+ _clip->render(ct, *carea, flags);
+ }
+ // render mask as an object, using a different color
+ if (_mask) {
+ _drawing.outlinecolor = prefs->getInt("/options/wireframecolors/masks", 0x0000ffff); // blue masks
+ _mask->render(ct, *carea, flags);
+ }
+ _drawing.outlinecolor = saved_rgba; // restore outline color
+}
+
+/** @brief Rasterize the clipping path.
+ * This method submits drawing operations required to draw a basic filled shape
+ * of the item to the supplied drawing context. Rendering is limited to the
+ * given area. The rendering of the clipped object is composited into
+ * the result of this call using the IN operator. See the implementation
+ * of render() for details.
+ */
+void
+DrawingItem::clip(Inkscape::DrawingContext &ct, Geom::IntRect const &area)
+{
+ // don't bother if the object does not implement clipping (e.g. DrawingImage)
+ if (!_canClip()) return;
+ if (!_visible) return;
+ if (!area.intersects(_bbox)) return;
+
+ // The item used as the clipping path itself has a clipping path.
+ // Render this item's clipping path onto a temporary surface, then composite it
+ // with the item using the IN operator
+ if (_clip) {
+ ct.pushAlphaGroup();
+ { Inkscape::DrawingContext::Save save(ct);
+ ct.setSource(0,0,0,1);
+ _clip->clip(ct, area);
+ }
+ ct.pushAlphaGroup();
+ }
+
+ // rasterize the clipping path
+ _clipItem(ct, area);
+
+ if (_clip) {
+ ct.popGroupToSource();
+ ct.setOperator(CAIRO_OPERATOR_IN);
+ ct.paint();
+ ct.popGroupToSource();
+ ct.setOperator(CAIRO_OPERATOR_SOURCE);
+ ct.paint();
+ }
+}
+
+/** @brief Get the item under the specified point.
+ * Searches the tree for the first item in the Z-order which is closer than
+ * @a delta to the given point. The pick should be visual - for example
+ * an object with a thick stroke should pick on the entire area of the stroke.
+ * @param p Search point
+ * @param delta Maximum allowed distance from the point
+ * @param sticky Whether the pick should ignore visibility and sensitivity.
+ * When false, only visible and sensitive objects are considered.
+ * When true, invisible and insensitive objects can also be picked.
+ */
+DrawingItem *
+DrawingItem::pick(Geom::Point const &p, double delta, unsigned flags)
+{
+ // Sometimes there's no BBOX in state, reason unknown (bug 992817)
+ // I made this not an assert to remove the warning
+ if (!(_state & STATE_BBOX) || !(_state & STATE_PICK))
+ return NULL;
+ // ignore invisible and insensitive items unless sticky
+ if (!(flags & PICK_STICKY) && !(_visible && _sensitive))
+ return NULL;
+
+ bool outline = _drawing.outline();
+
+ if (!_drawing.outline()) {
+ // pick inside clipping path; if NULL, it means the object is clipped away there
+ if (_clip) {
+ DrawingItem *cpick = _clip->pick(p, delta, flags | PICK_AS_CLIP);
+ if (!cpick) return NULL;
+ }
+ // same for mask
+ if (_mask) {
+ DrawingItem *mpick = _mask->pick(p, delta, flags);
+ if (!mpick) return NULL;
+ }
+ }
+
+ Geom::OptIntRect box = (outline || (flags & PICK_AS_CLIP)) ? _bbox : _drawbox;
+ if (!box) return NULL;
+
+ Geom::Rect expanded = *box;
+ expanded.expandBy(delta);
+
+ if (expanded.contains(p)) {
+ return _pickItem(p, delta, flags);
+ }
+ return NULL;
+}
+
+/** Marks the current visual bounding box of the item for redrawing.
+ * This is called whenever the object changes its visible appearance.
+ * For some cases (such as setting opacity) this is enough, but for others
+ * _markForUpdate() also needs to be called.
+ */
+void
+DrawingItem::_markForRendering()
+{
+ bool outline = _drawing.outline();
+ Geom::OptIntRect dirty = outline ? _bbox : _drawbox;
+ if (!dirty) return;
+
+ // dirty the caches of all parents
+ DrawingItem *bkg_root = NULL;
+
+ for (DrawingItem *i = this; i; i = i->_parent) {
+ if (i != this && i->_filter) {
+ i->_filter->area_enlarge(*dirty, i);
+ }
+ if (i->_cache) {
+ i->_cache->markDirty(*dirty);
+ }
+ if (i->_background_accumulate) {
+ bkg_root = i;
+ }
+ }
+
+ if (bkg_root) {
+ bkg_root->_invalidateFilterBackground(*dirty);
+ }
+ _drawing.signal_request_render.emit(*dirty);
+}
+
+void
+DrawingItem::_invalidateFilterBackground(Geom::IntRect const &area)
+{
+ if (!_drawbox.intersects(area)) return;
+
+ if (_cache && _filter && _filter->uses_background()) {
+ _cache->markDirty(area);
+ }
+
+ for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
+ i->_invalidateFilterBackground(area);
+ }
+}
+
+/** @brief Marks the item as needing a recomputation of internal data.
+ *
+ * This mechanism avoids traversing the entire rendering tree (which could be vast)
+ * on every trivial state changed in any item. Only items marked as needing
+ * an update (having some bits in their _state unset) will be traversed
+ * during the update call.
+ *
+ * The _propagate variable is another optimization. We use it to specify that
+ * all children should also have the corresponding flags unset before checking
+ * whether they need to be traversed. This way there is one less traversal
+ * of the tree. Without this we would need to unset state bits in all children.
+ * With _propagate we do this during the update call, when we have to traverse
+ * the tree anyway.
+ */
+void
+DrawingItem::_markForUpdate(unsigned flags, bool propagate)
+{
+ if (propagate) {
+ _propagate_state |= flags;
+ }
+
+ if (_state & flags) {
+ _state &= ~flags;
+ if (_parent) {
+ _parent->_markForUpdate(flags, false);
+ } else {
+ _drawing.signal_request_update.emit(this);
+ }
+ }
+}
+
+void
+DrawingItem::_setStyleCommon(SPStyle *&_style, SPStyle *style)
+{
+ if (style) sp_style_ref(style);
+ if (_style) sp_style_unref(_style);
+ _style = style;
+
+ // if group has a filter
+ if (style->filter.set && style->getFilter()) {
+ if (!_filter) {
+ int primitives = sp_filter_primitive_count(SP_FILTER(style->getFilter()));
+ _filter = new Inkscape::Filters::Filter(primitives);
+ }
+ sp_filter_build_renderer(SP_FILTER(style->getFilter()), _filter);
+ } else {
+ // no filter set for this group
+ delete _filter;
+ _filter = NULL;
+ }
+
+ if (style && style->enable_background.set) {
+ if (style->enable_background.value == SP_CSS_BACKGROUND_NEW && !_background_new) {
+ _background_new = true;
+ _markForUpdate(STATE_BACKGROUND, true);
+ } else if (style->enable_background.value == SP_CSS_BACKGROUND_ACCUMULATE && _background_new) {
+ _background_new = false;
+ _markForUpdate(STATE_BACKGROUND, true);
+ }
+ }
+
+ _markForUpdate(STATE_ALL, false);
+}
+
+/** @brief Compute the caching score.
+ *
+ * Higher scores mean the item is more aggresively prioritized for automatic
+ * caching by Inkscape::Drawing. */
+double
+DrawingItem::_cacheScore()
+{
+ Geom::OptIntRect cache_rect = _cacheRect();
+ if (!cache_rect) return -1.0;
+
+ // a crude first approximation:
+ // the basic score is the number of pixels in the drawbox
+ double score = cache_rect->area();
+ // this is multiplied by the filter complexity and its expansion
+ if (_filter &&_drawing.renderFilters()) {
+ score *= _filter->complexity(_ctm);
+ Geom::IntRect ref_area = Geom::IntRect::from_xywh(0, 0, 16, 16);
+ Geom::IntRect test_area = ref_area;
+ Geom::IntRect limit_area(0, INT_MIN, 16, INT_MAX);
+ _filter->area_enlarge(test_area, this);
+ // area_enlarge never shrinks the rect, so the result of intersection below
+ // must be non-empty
+ score *= double((test_area & limit_area)->area()) / ref_area.area();
+ }
+ // if the object is clipped, add 1/2 of its bbox pixels
+ if (_clip && _clip->_bbox) {
+ score += _clip->_bbox->area() * 0.5;
+ }
+ // if masked, add mask score
+ if (_mask) {
+ score += _mask->_cacheScore();
+ }
+ //g_message("caching score: %f", score);
+ return score;
+}
+
+Geom::OptIntRect
+DrawingItem::_cacheRect()
+{
+ Geom::OptIntRect r = _drawbox & _drawing.cacheLimit();
+ return r;
+}
+
+} // end namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/drawing-item.h b/src/display/drawing-item.h
new file mode 100644
index 000000000..424616427
--- /dev/null
+++ b/src/display/drawing-item.h
@@ -0,0 +1,212 @@
+/**
+ * @file
+ * @brief Canvas item belonging to an SVG drawing element
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2011 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_INKSCAPE_DISPLAY_DRAWING_ITEM_H
+#define SEEN_INKSCAPE_DISPLAY_DRAWING_ITEM_H
+
+#include <list>
+#include <exception>
+#include <boost/operators.hpp>
+#include <boost/utility.hpp>
+#include <boost/intrusive/list.hpp>
+#include <2geom/rect.h>
+#include <2geom/affine.h>
+#include "display/display-forward.h"
+
+class SPStyle;
+
+namespace Inkscape {
+
+struct UpdateContext {
+ Geom::Affine ctm;
+};
+
+struct CacheRecord
+ : boost::totally_ordered<CacheRecord>
+{
+ bool operator<(CacheRecord const &other) const { return score < other.score; }
+ bool operator==(CacheRecord const &other) const { return score == other.score; }
+ operator DrawingItem *() const { return item; }
+ double score;
+ size_t cache_size;
+ DrawingItem *item;
+};
+typedef std::list<CacheRecord> CacheList;
+
+class InvalidItemException : public std::exception {
+ virtual const char *what() const throw() {
+ return "Invalid item in drawing";
+ }
+};
+
+class DrawingItem
+ : boost::noncopyable
+{
+public:
+ enum RenderFlags {
+ RENDER_DEFAULT = 0,
+ RENDER_CACHE_ONLY = 1,
+ RENDER_BYPASS_CACHE = 2,
+ RENDER_FILTER_BACKGROUND = 4
+ };
+ enum StateFlags {
+ STATE_NONE = 0,
+ STATE_BBOX = (1<<0), // bounding boxes are up-to-date
+ STATE_CACHE = (1<<1), // cache extents and clean area are up-to-date
+ STATE_PICK = (1<<2), // can process pick requests
+ STATE_RENDER = (1<<3), // can be rendered
+ STATE_BACKGROUND = (1<<4), // filter background data is up to date
+ STATE_ALL = (1<<5)-1
+ };
+ enum PickFlags {
+ PICK_NORMAL = 0, // normal pick
+ PICK_STICKY = (1<<0), // sticky pick - ignore visibility and sensitivity
+ PICK_AS_CLIP = (1<<2) // pick with no stroke and opaque fill regardless of item style
+ };
+
+ DrawingItem(Drawing &drawing);
+ virtual ~DrawingItem();
+
+ Geom::OptIntRect geometricBounds() const { return _bbox; }
+ Geom::OptIntRect visualBounds() const { return _drawbox; }
+ Geom::OptRect itemBounds() const { return _item_bbox; }
+ Geom::Affine ctm() const { return _ctm; }
+ Geom::Affine transform() const { return _transform ? *_transform : Geom::identity(); }
+ Drawing &drawing() const { return _drawing; }
+ DrawingItem *parent() const;
+ bool isAncestorOf(DrawingItem *item) const;
+
+ void appendChild(DrawingItem *item);
+ void prependChild(DrawingItem *item);
+ void clearChildren();
+
+ bool visible() const { return _visible; }
+ void setVisible(bool v);
+ bool sensitive() const { return _sensitive; }
+ void setSensitive(bool v);
+ bool cached() const { return _cached; }
+ void setCached(bool c, bool persistent = false);
+
+ void setOpacity(float opacity);
+ void setTransform(Geom::Affine const &trans);
+ void setClip(DrawingItem *item);
+ void setMask(DrawingItem *item);
+ void setZOrder(unsigned z);
+ void setItemBounds(Geom::OptRect const &bounds);
+
+ void setKey(unsigned key) { _key = key; }
+ unsigned key() const { return _key; }
+ void setData(void *data) { _user_data = data; }
+ void *data() const { return _user_data; }
+
+ void update(Geom::IntRect const &area = Geom::IntRect::infinite(), UpdateContext const &ctx = UpdateContext(), unsigned flags = STATE_ALL, unsigned reset = 0);
+ unsigned render(DrawingContext &ct, Geom::IntRect const &area, unsigned flags = 0, DrawingItem *stop_at = NULL);
+ void clip(DrawingContext &ct, Geom::IntRect const &area);
+ DrawingItem *pick(Geom::Point const &p, double delta, unsigned flags = 0);
+
+protected:
+ enum ChildType {
+ CHILD_ORPHAN = 0, // no parent - implies _parent == NULL
+ CHILD_NORMAL = 1, // contained in _children of parent
+ CHILD_CLIP = 2, // referenced by _clip member of parent
+ CHILD_MASK = 3, // referenced by _mask member of parent
+ CHILD_ROOT = 4, // root item of _drawing
+ CHILD_FILL_PATTERN = 5, // not yet implemented: referenced by fill pattern of parent
+ CHILD_STROKE_PATTERN = 6 // not yet implemented: referenced by stroke pattern of parent
+ };
+ enum RenderResult {
+ RENDER_OK = 0,
+ RENDER_STOP = 1
+ };
+ void _renderOutline(DrawingContext &ct, Geom::IntRect const &area, unsigned flags);
+ void _markForUpdate(unsigned state, bool propagate);
+ void _markForRendering();
+ void _invalidateFilterBackground(Geom::IntRect const &area);
+ void _setStyleCommon(SPStyle *&_style, SPStyle *style);
+ double _cacheScore();
+ Geom::OptIntRect _cacheRect();
+ virtual unsigned _updateItem(Geom::IntRect const &area, UpdateContext const &ctx,
+ unsigned flags, unsigned reset) { return 0; }
+ virtual unsigned _renderItem(DrawingContext &ct, Geom::IntRect const &area, unsigned flags,
+ DrawingItem *stop_at) { return RENDER_OK; }
+ virtual void _clipItem(DrawingContext &ct, Geom::IntRect const &area) {}
+ virtual DrawingItem *_pickItem(Geom::Point const &p, double delta, unsigned flags) { return NULL; }
+ virtual bool _canClip() { return false; }
+
+ // member variables start here
+
+ Drawing &_drawing;
+ DrawingItem *_parent;
+
+ typedef boost::intrusive::list_member_hook<> ListHook;
+ ListHook _child_hook;
+
+ typedef boost::intrusive::list<
+ DrawingItem,
+ boost::intrusive::member_hook<DrawingItem, ListHook, &DrawingItem::_child_hook>
+ > ChildrenList;
+ ChildrenList _children;
+
+ unsigned _key; ///< Some SPItems can have more than one DrawingItem;
+ /// this value is a hack used to distinguish between them
+ float _opacity;
+
+ Geom::Affine *_transform; ///< Incremental transform from parent to this item's coords
+ Geom::Affine _ctm; ///< Total transform from item coords to display coords
+ Geom::OptIntRect _bbox; ///< Bounding box in display (pixel) coords including stroke
+ Geom::OptIntRect _drawbox; ///< Full visual bounding box - enlarged by filters, shrunk by clips and masks
+ Geom::OptRect _item_bbox; ///< Geometric bounding box in item coordinates
+
+ DrawingItem *_clip;
+ DrawingItem *_mask;
+ Inkscape::Filters::Filter *_filter;
+ void *_user_data; ///< Used to associate DrawingItems with SPItems that created them
+ DrawingCache *_cache;
+
+ CacheList::iterator _cache_iterator;
+
+ unsigned _state : 8;
+ unsigned _propagate_state : 8;
+ unsigned _child_type : 3; // see ChildType enum
+ unsigned _background_new : 1; ///< Whether enable-background: new is set for this element
+ unsigned _background_accumulate : 1; ///< Whether this element accumulates background
+ /// (has any ancestor with enable-background: new)
+ unsigned _visible : 1;
+ unsigned _sensitive : 1; ///< Whether this item responds to events
+ unsigned _cached : 1; ///< Whether the rendering is stored for reuse
+ unsigned _cached_persistent : 1; ///< If set, will always be cached regardless of score
+ unsigned _has_cache_iterator : 1; ///< If set, _cache_iterator is valid
+ unsigned _propagate : 1; ///< Whether to call update for all children on next update
+ //unsigned _renders_opacity : 1; ///< Whether object needs temporary surface for opacity
+ unsigned _pick_children : 1; ///< For groups: if true, children are returned from pick(),
+ /// otherwise the group is returned
+
+ friend class Drawing;
+};
+
+struct DeleteDisposer {
+ void operator()(DrawingItem *item) { delete item; }
+};
+
+} // end namespace Inkscape
+
+#endif // !SEEN_INKSCAPE_DISPLAY_DRAWING_ITEM_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/drawing-shape.cpp b/src/display/drawing-shape.cpp
new file mode 100644
index 000000000..ac0ff2ccb
--- /dev/null
+++ b/src/display/drawing-shape.cpp
@@ -0,0 +1,343 @@
+/**
+ * @file
+ * @brief Shape (styled path) belonging to an SVG drawing
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2011 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <glib.h>
+#include <2geom/curves.h>
+#include <2geom/pathvector.h>
+#include <2geom/svg-path.h>
+#include <2geom/svg-path-parser.h>
+
+#include "display/cairo-utils.h"
+#include "display/canvas-arena.h"
+#include "display/canvas-bpath.h"
+#include "display/curve.h"
+#include "display/drawing.h"
+#include "display/drawing-context.h"
+#include "display/drawing-group.h"
+#include "display/drawing-shape.h"
+#include "helper/geom-curves.h"
+#include "helper/geom.h"
+#include "libnr/nr-convert2geom.h"
+#include "preferences.h"
+#include "style.h"
+#include "svg/svg.h"
+
+namespace Inkscape {
+
+DrawingShape::DrawingShape(Drawing &drawing)
+ : DrawingItem(drawing)
+ , _curve(NULL)
+ , _style(NULL)
+ , _last_pick(NULL)
+ , _repick_after(0)
+{}
+
+DrawingShape::~DrawingShape()
+{
+ if (_style)
+ sp_style_unref(_style);
+ if (_curve)
+ _curve->unref();
+}
+
+void
+DrawingShape::setPath(SPCurve *curve)
+{
+ _markForRendering();
+
+ if (_curve) {
+ _curve->unref();
+ _curve = NULL;
+ }
+ if (curve) {
+ _curve = curve;
+ curve->ref();
+ }
+
+ _markForUpdate(STATE_ALL, false);
+}
+
+void
+DrawingShape::setStyle(SPStyle *style)
+{
+ _setStyleCommon(_style, style);
+ _nrstyle.set(style);
+}
+
+unsigned
+DrawingShape::_updateItem(Geom::IntRect const &area, UpdateContext const &ctx, unsigned flags, unsigned reset)
+{
+ Geom::OptRect boundingbox;
+
+ unsigned beststate = STATE_ALL;
+
+ // update markers
+ for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
+ i->update(area, ctx, flags, reset);
+ }
+
+ if (!(flags & STATE_RENDER)) {
+ /* We do not have to create rendering structures */
+ if (flags & STATE_BBOX) {
+ if (_curve) {
+ boundingbox = bounds_exact_transformed(_curve->get_pathvector(), ctx.ctm);
+ if (boundingbox) {
+ _bbox = boundingbox->roundOutwards();
+ } else {
+ _bbox = Geom::OptIntRect();
+ }
+ }
+ if (beststate & STATE_BBOX) {
+ for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
+ _bbox.unionWith(i->geometricBounds());
+ }
+ }
+ }
+ return (flags | _state);
+ }
+
+ boundingbox = Geom::OptRect();
+ bool outline = _drawing.outline();
+
+ // clear Cairo data to force update
+ _nrstyle.update();
+
+ if (_curve) {
+ boundingbox = bounds_exact_transformed(_curve->get_pathvector(), ctx.ctm);
+
+ if (boundingbox && (_nrstyle.stroke.type != NRStyle::PAINT_NONE || outline)) {
+ float width, scale;
+ scale = ctx.ctm.descrim();
+ width = std::max(0.125f, _nrstyle.stroke_width * scale);
+ if ( fabs(_nrstyle.stroke_width * scale) > 0.01 ) { // FIXME: this is always true
+ boundingbox->expandBy(width);
+ }
+ // those pesky miters, now
+ float miterMax = width * _nrstyle.miter_limit;
+ if ( miterMax > 0.01 ) {
+ // grunt mode. we should compute the various miters instead
+ // (one for each point on the curve)
+ boundingbox->expandBy(miterMax);
+ }
+ }
+ }
+
+ _bbox = boundingbox ? boundingbox->roundOutwards() : Geom::OptIntRect();
+
+ if (!_curve ||
+ !_style ||
+ _curve->is_empty() ||
+ (( _nrstyle.fill.type != NRStyle::PAINT_NONE ) &&
+ ( _nrstyle.stroke.type != NRStyle::PAINT_NONE && !outline) ))
+ {
+ return STATE_ALL;
+ }
+
+ if (beststate & STATE_BBOX) {
+ for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
+ _bbox.unionWith(i->geometricBounds());
+ }
+ }
+
+ return STATE_ALL;
+}
+
+unsigned
+DrawingShape::_renderItem(DrawingContext &ct, Geom::IntRect const &area, unsigned flags, DrawingItem *stop_at)
+{
+ if (!_curve || !_style) return RENDER_OK;
+ if (!area.intersects(_bbox)) return RENDER_OK; // skip if not within bounding box
+
+ bool outline = _drawing.outline();
+
+ if (outline) {
+ guint32 rgba = _drawing.outlinecolor;
+
+ { Inkscape::DrawingContext::Save save(ct);
+ ct.transform(_ctm);
+ ct.path(_curve->get_pathvector());
+ }
+ { Inkscape::DrawingContext::Save save(ct);
+ ct.setSource(rgba);
+ ct.setLineWidth(0.5);
+ ct.setTolerance(1.25);
+ ct.stroke();
+ }
+ } else {
+ bool has_stroke, has_fill;
+ // we assume the context has no path
+ Inkscape::DrawingContext::Save save(ct);
+ ct.transform(_ctm);
+
+ // update fill and stroke paints.
+ // this cannot be done during nr_arena_shape_update, because we need a Cairo context
+ // to render svg:pattern
+ has_fill = _nrstyle.prepareFill(ct, _item_bbox);
+ has_stroke = _nrstyle.prepareStroke(ct, _item_bbox);
+ has_stroke &= (_nrstyle.stroke_width != 0);
+
+ if (has_fill || has_stroke) {
+ // TODO: remove segments outside of bbox when no dashes present
+ ct.path(_curve->get_pathvector());
+ if (has_fill) {
+ _nrstyle.applyFill(ct);
+ ct.fillPreserve();
+ }
+ if (has_stroke) {
+ _nrstyle.applyStroke(ct);
+ ct.strokePreserve();
+ }
+ ct.newPath(); // clear path
+ } // has fill or stroke pattern
+ }
+
+ // marker rendering
+ for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
+ i->render(ct, area, flags, stop_at);
+ }
+ return RENDER_OK;
+}
+
+void
+DrawingShape::_clipItem(DrawingContext &ct, Geom::IntRect const &area)
+{
+ if (!_curve) return;
+
+ Inkscape::DrawingContext::Save save(ct);
+ // handle clip-rule
+ if (_style) {
+ if (_style->clip_rule.computed == SP_WIND_RULE_EVENODD) {
+ ct.setFillRule(CAIRO_FILL_RULE_EVEN_ODD);
+ } else {
+ ct.setFillRule(CAIRO_FILL_RULE_WINDING);
+ }
+ }
+ ct.transform(_ctm);
+ ct.path(_curve->get_pathvector());
+ ct.fill();
+}
+
+DrawingItem *
+DrawingShape::_pickItem(Geom::Point const &p, double delta, unsigned flags)
+{
+ if (_repick_after > 0)
+ --_repick_after;
+
+ if (_repick_after > 0) // we are a slow, huge path
+ return _last_pick; // skip this pick, returning what was returned last time
+
+ if (!_curve) return NULL;
+ if (!_style) return NULL;
+
+ bool outline = _drawing.outline();
+ bool pick_as_clip = flags & PICK_AS_CLIP;
+
+ if (SP_SCALE24_TO_FLOAT(_style->opacity.value) == 0 && !outline && !pick_as_clip)
+ // fully transparent, no pick unless outline mode
+ return NULL;
+
+ GTimeVal tstart, tfinish;
+ g_get_current_time (&tstart);
+
+ double width;
+ if (pick_as_clip) {
+ width = 0; // no width should be applied to clip picking
+ // this overrides display mode and stroke style considerations
+ } else if (outline) {
+ width = 0.5; // in outline mode, everything is stroked with the same 0.5px line width
+ } else if (_nrstyle.stroke.type != NRStyle::PAINT_NONE && _nrstyle.stroke.opacity > 1e-3) {
+ // for normal picking calculate the distance corresponding top the stroke width
+ // FIXME BUG: this is incorrect for transformed strokes
+ float const scale = _ctm.descrim();
+ width = std::max(0.125f, _nrstyle.stroke_width * scale) / 2;
+ } else {
+ width = 0;
+ }
+
+ double dist = Geom::infinity();
+ int wind = 0;
+ bool needfill = pick_as_clip || (_nrstyle.fill.type != NRStyle::PAINT_NONE &&
+ _nrstyle.fill.opacity > 1e-3 && !outline);
+ bool wind_evenodd = pick_as_clip ? (_style->clip_rule.computed == SP_WIND_RULE_EVENODD) :
+ (_style->fill_rule.computed == SP_WIND_RULE_EVENODD);
+
+ // actual shape picking
+ if (_drawing.arena()) {
+ Geom::Rect viewbox = _drawing.arena()->item.canvas->getViewbox();
+ viewbox.expandBy (width);
+ pathv_matrix_point_bbox_wind_distance(_curve->get_pathvector(), _ctm, p, NULL, needfill? &wind : NULL, &dist, 0.5, &viewbox);
+ } else {
+ pathv_matrix_point_bbox_wind_distance(_curve->get_pathvector(), _ctm, p, NULL, needfill? &wind : NULL, &dist, 0.5, NULL);
+ }
+
+ g_get_current_time (&tfinish);
+ glong this_pick = (tfinish.tv_sec - tstart.tv_sec) * 1000000 + (tfinish.tv_usec - tstart.tv_usec);
+ //g_print ("pick time %lu\n", this_pick);
+
+ if (this_pick > 10000) { // slow picking, remember to skip several new picks
+ _repick_after = this_pick / 5000;
+ }
+
+ // covered by fill?
+ if (needfill) {
+ if (wind_evenodd) {
+ if (wind & 0x1) {
+ _last_pick = this;
+ return this;
+ }
+ } else {
+ if (wind != 0) {
+ _last_pick = this;
+ return this;
+ }
+ }
+ }
+
+ // close to the edge, as defined by strokewidth and delta?
+ // this ignores dashing (as if the stroke is solid) and always works as if caps are round
+ if (needfill || width > 0) { // if either fill or stroke visible,
+ if ((dist - width) < delta) {
+ _last_pick = this;
+ return this;
+ }
+ }
+
+ // if not picked on the shape itself, try its markers
+ for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
+ DrawingItem *ret = i->pick(p, delta, flags & ~PICK_STICKY);
+ if (ret) {
+ _last_pick = this;
+ return this;
+ }
+ }
+
+ _last_pick = NULL;
+ return NULL;
+}
+
+bool
+DrawingShape::_canClip()
+{
+ return true;
+}
+
+} // end namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/drawing-shape.h b/src/display/drawing-shape.h
new file mode 100644
index 000000000..27bd7fbba
--- /dev/null
+++ b/src/display/drawing-shape.h
@@ -0,0 +1,63 @@
+/**
+ * @file
+ * @brief Group belonging to an SVG drawing element
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2011 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_INKSCAPE_DISPLAY_DRAWING_SHAPE_H
+#define SEEN_INKSCAPE_DISPLAY_DRAWING_SHAPE_H
+
+#include "display/drawing-item.h"
+#include "display/nr-style.h"
+
+class SPStyle;
+class SPCurve;
+
+namespace Inkscape {
+
+class DrawingShape
+ : public DrawingItem
+{
+public:
+ DrawingShape(Drawing &drawing);
+ ~DrawingShape();
+
+ void setPath(SPCurve *curve);
+ void setStyle(SPStyle *style);
+
+protected:
+ virtual unsigned _updateItem(Geom::IntRect const &area, UpdateContext const &ctx,
+ unsigned flags, unsigned reset);
+ virtual unsigned _renderItem(DrawingContext &ct, Geom::IntRect const &area, unsigned flags,
+ DrawingItem *stop_at);
+ virtual void _clipItem(DrawingContext &ct, Geom::IntRect const &area);
+ virtual DrawingItem *_pickItem(Geom::Point const &p, double delta, unsigned flags);
+ virtual bool _canClip();
+
+ SPCurve *_curve;
+ SPStyle *_style;
+ NRStyle _nrstyle;
+
+ DrawingItem *_last_pick;
+ unsigned _repick_after;
+};
+
+} // end namespace Inkscape
+
+#endif // !SEEN_INKSCAPE_DISPLAY_DRAWING_ITEM_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/drawing-surface.cpp b/src/display/drawing-surface.cpp
new file mode 100644
index 000000000..5cbfaa3fe
--- /dev/null
+++ b/src/display/drawing-surface.cpp
@@ -0,0 +1,354 @@
+/**
+ * @file
+ * @brief Cairo surface that remembers its origin
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2011 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+//#include <iostream>
+#include "display/drawing-surface.h"
+#include "display/drawing-context.h"
+#include "display/cairo-utils.h"
+
+namespace Inkscape {
+
+using Geom::X;
+using Geom::Y;
+
+
+/** @class DrawingSurface
+ * @brief Drawing surface that remembers its origin.
+ *
+ * This is a very minimalistic wrapper over cairo_surface_t. The main
+ * extra functionality provided by this class is that it automates
+ * the mapping from "logical space" (coordinates in the rendering)
+ * and the "physical space" (surface pixels). For example, patterns
+ * have to be rendered on tiles which have possibly non-integer
+ * widths and heights.
+ *
+ * This class has delayed allocation functionality - it creates
+ * the Cairo surface it wraps on the first call to createRawContext()
+ * of when a DrawingContext is constructed.
+ */
+
+/** @brief Creates a surface with the given physical extents.
+ * When a drawing context is created for this surface, its pixels
+ * will cover the area under the given rectangle. */
+DrawingSurface::DrawingSurface(Geom::IntRect const &area)
+ : _surface(NULL)
+ , _origin(area.min())
+ , _scale(1, 1)
+ , _pixels(area.dimensions())
+{}
+
+/** @brief Creates a surface with the given logical and physical extents.
+ * When a drawing context is created for this surface, its pixels
+ * will cover the area under the given rectangle. IT will contain
+ * the number of pixels specified by the second argument.
+ * @param logbox Logical extents of the surface
+ * @param pixdims Pixel dimensions of the surface. */
+DrawingSurface::DrawingSurface(Geom::Rect const &logbox, Geom::IntPoint const &pixdims)
+ : _surface(NULL)
+ , _origin(logbox.min())
+ , _scale(pixdims[X] / logbox.width(), pixdims[Y] / logbox.height())
+ , _pixels(pixdims)
+{}
+
+/** @brief Wrap a cairo_surface_t.
+ * This constructor will take an extra reference on @a surface, which will
+ * be released on destruction. */
+DrawingSurface::DrawingSurface(cairo_surface_t *surface, Geom::Point const &origin)
+ : _surface(surface)
+ , _origin(origin)
+ , _scale(1, 1)
+{
+ cairo_surface_reference(surface);
+ _pixels[X] = cairo_image_surface_get_width(surface);
+ _pixels[Y] = cairo_image_surface_get_height(surface);
+}
+
+DrawingSurface::~DrawingSurface()
+{
+ if (_surface)
+ cairo_surface_destroy(_surface);
+}
+
+/// Get the logical extents of the surface.
+Geom::Rect
+DrawingSurface::area() const
+{
+ Geom::Rect r = Geom::Rect::from_xywh(_origin, dimensions());
+ return r;
+}
+
+/// Get the pixel dimensions of the surface
+Geom::IntPoint
+DrawingSurface::pixels() const
+{
+ return _pixels;
+}
+
+/// Get the logical width and weight of the surface as a point.
+Geom::Point
+DrawingSurface::dimensions() const
+{
+ Geom::Point logical_dims(_pixels[X] / _scale[X], _pixels[Y] / _scale[Y]);
+ return logical_dims;
+}
+
+Geom::Point
+DrawingSurface::origin() const
+{
+ return _origin;
+}
+
+Geom::Scale
+DrawingSurface::scale() const
+{
+ return _scale;
+}
+
+/// Get the transformation applied to the drawing context on construction.
+Geom::Affine
+DrawingSurface::drawingTransform() const
+{
+ Geom::Affine ret = _scale * Geom::Translate(-_origin);
+ return ret;
+}
+
+cairo_surface_type_t
+DrawingSurface::type() const
+{
+ // currently hardcoded
+ return CAIRO_SURFACE_TYPE_IMAGE;
+}
+
+/// Drop contents of the surface and release the underlying Cairo object.
+void
+DrawingSurface::dropContents()
+{
+ if (_surface) {
+ cairo_surface_destroy(_surface);
+ _surface = NULL;
+ }
+}
+
+/** @brief Create a drawing context for this surface.
+ * It's better to use the surface constructor of DrawingContext. */
+cairo_t *
+DrawingSurface::createRawContext()
+{
+ // deferred allocation
+ if (!_surface) {
+ _surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, _pixels[X], _pixels[Y]);
+ }
+ cairo_t *ct = cairo_create(_surface);
+ if (_scale != Geom::Scale::identity()) {
+ cairo_scale(ct, _scale[X], _scale[Y]);
+ }
+ cairo_translate(ct, -_origin[X], -_origin[Y]);
+ return ct;
+}
+
+Geom::IntRect
+DrawingSurface::pixelArea() const
+{
+ Geom::IntRect ret = Geom::IntRect::from_xywh(_origin.round(), _pixels);
+ return ret;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+DrawingCache::DrawingCache(Geom::IntRect const &area)
+ : DrawingSurface(area)
+ , _clean_region(cairo_region_create())
+ , _pending_area(area)
+{}
+
+DrawingCache::~DrawingCache()
+{
+ cairo_region_destroy(_clean_region);
+}
+
+void
+DrawingCache::markDirty(Geom::IntRect const &area)
+{
+ cairo_rectangle_int_t dirty = _convertRect(area);
+ cairo_region_subtract_rectangle(_clean_region, &dirty);
+}
+void
+DrawingCache::markClean(Geom::IntRect const &area)
+{
+ Geom::OptIntRect r = Geom::intersect(area, pixelArea());
+ if (!r) return;
+ cairo_rectangle_int_t clean = _convertRect(*r);
+ cairo_region_union_rectangle(_clean_region, &clean);
+}
+
+/// Call this during the update phase to schedule a transformation of the cache.
+void
+DrawingCache::scheduleTransform(Geom::IntRect const &new_area, Geom::Affine const &trans)
+{
+ _pending_area = new_area;
+ _pending_transform *= trans;
+}
+
+/// Transforms the cache according to the transform specified during the update phase.
+/// Call this during render phase, before painting.
+void
+DrawingCache::prepare()
+{
+ Geom::IntRect old_area = pixelArea();
+ bool is_identity = _pending_transform.isIdentity();
+ if (is_identity && _pending_area == old_area) return; // no change
+
+ bool is_integer_translation = false;
+ if (!is_identity && _pending_transform.isTranslation()) {
+ Geom::IntPoint t = _pending_transform.translation().round();
+ if (Geom::are_near(Geom::Point(t), _pending_transform.translation())) {
+ is_integer_translation = true;
+ cairo_region_translate(_clean_region, t[X], t[Y]);
+ if (old_area + t == _pending_area) {
+ // if the areas match, the only thing to do
+ // is to ensure that the clean area is not too large
+ cairo_rectangle_int_t limit = _convertRect(_pending_area);
+ cairo_region_intersect_rectangle(_clean_region, &limit);
+ _origin += t;
+ _pending_transform.setIdentity();
+ return;
+ }
+ }
+ }
+ // otherwise, we need to transform the cache
+ Geom::IntPoint old_origin = old_area.min();
+ cairo_surface_t *old_surface = _surface;
+ _surface = NULL;
+ _pixels = _pending_area.dimensions();
+ _origin = _pending_area.min();
+
+ cairo_t *ct = createRawContext();
+ if (!is_identity) {
+ ink_cairo_transform(ct, _pending_transform);
+ }
+ cairo_set_source_surface(ct, old_surface, old_origin[X], old_origin[Y]);
+ cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE);
+ cairo_paint(ct);
+
+ cairo_surface_destroy(old_surface);
+ cairo_destroy(ct);
+
+ if (!is_identity && !is_integer_translation) {
+ // dirty everything
+ cairo_region_destroy(_clean_region);
+ _clean_region = cairo_region_create();
+ } else {
+ cairo_rectangle_int_t limit = _convertRect(_pending_area);
+ cairo_region_intersect_rectangle(_clean_region, &limit);
+ }
+ //std::cout << _pending_transform << old_area << _pending_area << std::endl;
+ _pending_transform.setIdentity();
+}
+
+/** @brief Paints the clean area from cache and modifies the @a area
+ * parameter to the bounds of the region that must be repainted. */
+void
+DrawingCache::paintFromCache(DrawingContext &ct, Geom::OptIntRect &area)
+{
+ if (!area) return;
+
+ // We subtract the clean region from the area, then get the bounds
+ // of the resulting region. This is the area that needs to be repainted
+ // by the item.
+ // Then we subtract the area that needs to be repainted from the
+ // original area and paint the resulting region from cache.
+ cairo_rectangle_int_t area_c = _convertRect(*area);
+ cairo_region_t *dirty_region = cairo_region_create_rectangle(&area_c);
+ cairo_region_t *cache_region = cairo_region_copy(dirty_region);
+ cairo_region_subtract(dirty_region, _clean_region);
+
+ if (cairo_region_is_empty(dirty_region)) {
+ area = Geom::OptIntRect();
+ } else {
+ cairo_rectangle_int_t to_repaint;
+ cairo_region_get_extents(dirty_region, &to_repaint);
+ area = _convertRect(to_repaint);
+ cairo_region_subtract_rectangle(cache_region, &to_repaint);
+ }
+ cairo_region_destroy(dirty_region);
+
+ if (!cairo_region_is_empty(cache_region)) {
+ int nr = cairo_region_num_rectangles(cache_region);
+ cairo_rectangle_int_t tmp;
+ for (int i = 0; i < nr; ++i) {
+ cairo_region_get_rectangle(cache_region, i, &tmp);
+ ct.rectangle(_convertRect(tmp));
+ }
+ ct.setSource(this);
+ ct.fill();
+ }
+ cairo_region_destroy(cache_region);
+}
+
+// debugging utility
+void
+DrawingCache::_dumpCache(Geom::OptIntRect const &area)
+{
+ static int dumpnr = 0;
+ cairo_surface_t *surface = ink_cairo_surface_copy(_surface);
+ DrawingContext ct(surface, _origin);
+ if (!cairo_region_is_empty(_clean_region)) {
+ Inkscape::DrawingContext::Save save(ct);
+ int nr = cairo_region_num_rectangles(_clean_region);
+ cairo_rectangle_int_t tmp;
+ for (int i = 0; i < nr; ++i) {
+ cairo_region_get_rectangle(_clean_region, i, &tmp);
+ ct.rectangle(_convertRect(tmp));
+ }
+ ct.setSource(0,1,0,0.1);
+ ct.fill();
+ }
+ ct.rectangle(*area);
+ ct.setSource(1,0,0,0.1);
+ ct.fill();
+ char *fn = g_strdup_printf("dump%d.png", dumpnr++);
+ cairo_surface_write_to_png(surface, fn);
+ cairo_surface_destroy(surface);
+ g_free(fn);
+}
+
+cairo_rectangle_int_t
+DrawingCache::_convertRect(Geom::IntRect const &area)
+{
+ cairo_rectangle_int_t ret;
+ ret.x = area.left();
+ ret.y = area.top();
+ ret.width = area.width();
+ ret.height = area.height();
+ return ret;
+}
+
+Geom::IntRect
+DrawingCache::_convertRect(cairo_rectangle_int_t const &r)
+{
+ Geom::IntRect ret = Geom::IntRect::from_xywh(
+ r.x, r.y,
+ r.width, r.height);
+ return ret;
+}
+
+} // end namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/drawing-surface.h b/src/display/drawing-surface.h
new file mode 100644
index 000000000..e3637d402
--- /dev/null
+++ b/src/display/drawing-surface.h
@@ -0,0 +1,93 @@
+/**
+ * @file
+ * @brief Cairo surface that remembers its origin
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2011 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_INKSCAPE_DISPLAY_DRAWING_SURFACE_H
+#define SEEN_INKSCAPE_DISPLAY_DRAWING_SURFACE_H
+
+#include <boost/shared_ptr.hpp>
+#include <cairo.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <2geom/affine.h>
+#include <2geom/rect.h>
+#include <2geom/transforms.h>
+
+namespace Inkscape {
+class DrawingContext;
+
+class DrawingSurface
+{
+public:
+ explicit DrawingSurface(Geom::IntRect const &area);
+ DrawingSurface(Geom::Rect const &logbox, Geom::IntPoint const &pixdims);
+ DrawingSurface(cairo_surface_t *surface, Geom::Point const &origin);
+ virtual ~DrawingSurface();
+
+ Geom::Rect area() const;
+ Geom::IntPoint pixels() const;
+ Geom::Point dimensions() const;
+ Geom::Point origin() const;
+ Geom::Scale scale() const;
+ Geom::Affine drawingTransform() const;
+ cairo_surface_type_t type() const;
+ void dropContents();
+
+ cairo_surface_t *raw() { return _surface; }
+ cairo_t *createRawContext();
+
+protected:
+ Geom::IntRect pixelArea() const;
+
+ cairo_surface_t *_surface;
+ Geom::Point _origin;
+ Geom::Scale _scale;
+ Geom::IntPoint _pixels;
+ bool _has_context;
+
+ friend class DrawingContext;
+};
+
+class DrawingCache
+ : public DrawingSurface
+{
+public:
+ explicit DrawingCache(Geom::IntRect const &area);
+ ~DrawingCache();
+
+ void markDirty(Geom::IntRect const &area = Geom::IntRect::infinite());
+ void markClean(Geom::IntRect const &area = Geom::IntRect::infinite());
+ void scheduleTransform(Geom::IntRect const &new_area, Geom::Affine const &trans);
+ void prepare();
+ void paintFromCache(DrawingContext &ct, Geom::OptIntRect &area);
+
+protected:
+ cairo_region_t *_clean_region;
+ Geom::IntRect _pending_area;
+ Geom::Affine _pending_transform;
+private:
+ void _dumpCache(Geom::OptIntRect const &area);
+ static cairo_rectangle_int_t _convertRect(Geom::IntRect const &r);
+ static Geom::IntRect _convertRect(cairo_rectangle_int_t const &r);
+};
+
+} // end namespace Inkscape
+
+#endif // !SEEN_INKSCAPE_DISPLAY_DRAWING_ITEM_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/drawing-text.cpp b/src/display/drawing-text.cpp
new file mode 100644
index 000000000..1134771bc
--- /dev/null
+++ b/src/display/drawing-text.cpp
@@ -0,0 +1,255 @@
+/**
+ * @file
+ * @brief Group belonging to an SVG drawing element
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2011 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "display/cairo-utils.h"
+#include "display/canvas-bpath.h" // for SPWindRule (WTF!)
+#include "display/drawing.h"
+#include "display/drawing-context.h"
+#include "display/drawing-surface.h"
+#include "display/drawing-text.h"
+#include "helper/geom.h"
+#include "libnrtype/font-instance.h"
+#include "style.h"
+
+namespace Inkscape {
+
+DrawingGlyphs::DrawingGlyphs(Drawing &drawing)
+ : DrawingItem(drawing)
+ , _font(NULL)
+ , _glyph(0)
+{}
+
+DrawingGlyphs::~DrawingGlyphs()
+{
+ if (_font) {
+ _font->Unref();
+ _font = NULL;
+ }
+}
+
+void
+DrawingGlyphs::setGlyph(font_instance *font, int glyph, Geom::Affine const &trans)
+{
+ _markForRendering();
+
+ setTransform(trans);
+
+ if (font) font->Ref();
+ if (_font) _font->Unref();
+ _font = font;
+ _glyph = glyph;
+
+ _markForUpdate(STATE_ALL, false);
+}
+
+unsigned
+DrawingGlyphs::_updateItem(Geom::IntRect const &area, UpdateContext const &ctx, unsigned flags, unsigned reset)
+{
+ DrawingText *ggroup = dynamic_cast<DrawingText *>(_parent);
+ if (!ggroup) throw InvalidItemException();
+
+ if (!_font || !ggroup->_style) return STATE_ALL;
+ if (ggroup->_nrstyle.fill.type == NRStyle::PAINT_NONE &&
+ ggroup->_nrstyle.stroke.type == NRStyle::PAINT_NONE)
+ {
+ return STATE_ALL;
+ }
+
+ Geom::OptRect b = bounds_exact_transformed(*_font->PathVector(_glyph), ctx.ctm);
+ if (b && ggroup->_nrstyle.stroke.type != NRStyle::PAINT_NONE) {
+ float width, scale;
+ scale = ctx.ctm.descrim();
+ width = MAX(0.125, ggroup->_nrstyle.stroke_width * scale);
+ if ( fabs(ggroup->_nrstyle.stroke_width * scale) > 0.01 ) { // FIXME: this is always true
+ b->expandBy(width);
+ }
+ // those pesky miters, now
+ float miterMax = width * ggroup->_nrstyle.miter_limit;
+ if ( miterMax > 0.01 ) {
+ // grunt mode. we should compute the various miters instead
+ // (one for each point on the curve)
+ b->expandBy(miterMax);
+ }
+ }
+
+ if (b) {
+ _bbox = b->roundOutwards();
+ } else {
+ _bbox = Geom::OptIntRect();
+ }
+
+ return STATE_ALL;
+}
+
+DrawingItem *
+DrawingGlyphs::_pickItem(Geom::Point const &p, double delta, unsigned /*flags*/)
+{
+ if (!_font || !_bbox) return NULL;
+
+ // With text we take a simple approach: pick if the point is in a characher bbox
+ Geom::Rect expanded(*_bbox);
+ expanded.expandBy(delta);
+ if (expanded.contains(p)) return this;
+ return NULL;
+}
+
+
+
+DrawingText::DrawingText(Drawing &drawing)
+ : DrawingGroup(drawing)
+{}
+
+DrawingText::~DrawingText()
+{}
+
+void
+DrawingText::clear()
+{
+ _markForRendering();
+ _children.clear_and_dispose(DeleteDisposer());
+}
+
+void
+DrawingText::addComponent(font_instance *font, int glyph, Geom::Affine const &trans)
+{
+ if (!font || !font->PathVector(glyph)) return;
+
+ _markForRendering();
+ DrawingGlyphs *ng = new DrawingGlyphs(_drawing);
+ ng->setGlyph(font, glyph, trans);
+ appendChild(ng);
+}
+
+void
+DrawingText::setStyle(SPStyle *style)
+{
+ _nrstyle.set(style);
+ DrawingGroup::setStyle(style);
+}
+
+void
+DrawingText::setPaintBox(Geom::OptRect const &box)
+{
+ _paintbox = box;
+ _markForUpdate(STATE_ALL, false);
+}
+
+unsigned
+DrawingText::_updateItem(Geom::IntRect const &area, UpdateContext const &ctx, unsigned flags, unsigned reset)
+{
+ _nrstyle.update();
+ return DrawingGroup::_updateItem(area, ctx, flags, reset);
+}
+
+unsigned
+DrawingText::_renderItem(DrawingContext &ct, Geom::IntRect const &area, unsigned flags, DrawingItem *stop_at)
+{
+ if (_drawing.outline()) {
+ guint32 rgba = _drawing.outlinecolor;
+ Inkscape::DrawingContext::Save save(ct);
+ ct.setSource(rgba);
+ ct.setTolerance(1.25); // low quality, but good enough for outline mode
+
+ for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
+ DrawingGlyphs *g = dynamic_cast<DrawingGlyphs *>(&*i);
+ if (!g) throw InvalidItemException();
+
+ Inkscape::DrawingContext::Save save(ct);
+ // skip glpyhs with singular transforms
+ if (g->_ctm.isSingular()) continue;
+ ct.transform(g->_ctm);
+ ct.path(*g->_font->PathVector(g->_glyph));
+ ct.fill();
+ }
+ return RENDER_OK;
+ }
+
+ // NOTE: this is very similar to drawing-shape.cpp; the only difference is in path feeding
+ bool has_stroke, has_fill;
+
+ has_fill = _nrstyle.prepareFill(ct, _paintbox);
+ has_stroke = _nrstyle.prepareStroke(ct, _paintbox);
+
+ if (has_fill || has_stroke) {
+ for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
+ DrawingGlyphs *g = dynamic_cast<DrawingGlyphs *>(&*i);
+ if (!g) throw InvalidItemException();
+
+ Inkscape::DrawingContext::Save save(ct);
+ if (g->_ctm.isSingular()) continue;
+ ct.transform(g->_ctm);
+ ct.path(*g->_font->PathVector(g->_glyph));
+ }
+
+ if (has_fill) {
+ _nrstyle.applyFill(ct);
+ ct.fillPreserve();
+ }
+ if (has_stroke) {
+ _nrstyle.applyStroke(ct);
+ ct.strokePreserve();
+ }
+ ct.newPath(); // clear path
+ }
+ return RENDER_OK;
+}
+
+void
+DrawingText::_clipItem(DrawingContext &ct, Geom::IntRect const &area)
+{
+ Inkscape::DrawingContext::Save save(ct);
+
+ // handle clip-rule
+ if (_style) {
+ if (_style->clip_rule.computed == SP_WIND_RULE_EVENODD) {
+ ct.setFillRule(CAIRO_FILL_RULE_EVEN_ODD);
+ } else {
+ ct.setFillRule(CAIRO_FILL_RULE_WINDING);
+ }
+ }
+
+ for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
+ DrawingGlyphs *g = dynamic_cast<DrawingGlyphs *>(&*i);
+ if (!g) throw InvalidItemException();
+
+ Inkscape::DrawingContext::Save save(ct);
+ ct.transform(g->_ctm);
+ ct.path(*g->_font->PathVector(g->_glyph));
+ }
+ ct.fill();
+}
+
+DrawingItem *
+DrawingText::_pickItem(Geom::Point const &p, double delta, unsigned flags)
+{
+ DrawingItem *picked = DrawingGroup::_pickItem(p, delta, flags);
+ if (picked) return this;
+ return NULL;
+}
+
+bool
+DrawingText::_canClip()
+{
+ return true;
+}
+
+} // end namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/drawing-text.h b/src/display/drawing-text.h
new file mode 100644
index 000000000..4f3940dde
--- /dev/null
+++ b/src/display/drawing-text.h
@@ -0,0 +1,83 @@
+/**
+ * @file
+ * @brief Group belonging to an SVG drawing element
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2011 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_INKSCAPE_DISPLAY_DRAWING_TEXT_H
+#define SEEN_INKSCAPE_DISPLAY_DRAWING_TEXT_H
+
+#include "display/drawing-group.h"
+#include "display/nr-style.h"
+
+class SPStyle;
+class font_instance;
+
+namespace Inkscape {
+
+class DrawingGlyphs
+ : public DrawingItem
+{
+public:
+ DrawingGlyphs(Drawing &drawing);
+ ~DrawingGlyphs();
+
+ void setGlyph(font_instance *font, int glyph, Geom::Affine const &trans);
+
+protected:
+ unsigned _updateItem(Geom::IntRect const &area, UpdateContext const &ctx,
+ unsigned flags, unsigned reset);
+ virtual DrawingItem *_pickItem(Geom::Point const &p, double delta, unsigned flags);
+
+ font_instance *_font;
+ int _glyph;
+
+ friend class DrawingText;
+};
+
+class DrawingText
+ : public DrawingGroup
+{
+public:
+ DrawingText(Drawing &drawing);
+ ~DrawingText();
+
+ void clear();
+ void addComponent(font_instance *font, int glyph, Geom::Affine const &trans);
+ void setStyle(SPStyle *style);
+ void setPaintBox(Geom::OptRect const &box);
+
+protected:
+ virtual unsigned _updateItem(Geom::IntRect const &area, UpdateContext const &ctx,
+ unsigned flags, unsigned reset);
+ virtual unsigned _renderItem(DrawingContext &ct, Geom::IntRect const &area, unsigned flags,
+ DrawingItem *stop_at);
+ virtual void _clipItem(DrawingContext &ct, Geom::IntRect const &area);
+ virtual DrawingItem *_pickItem(Geom::Point const &p, double delta, unsigned flags);
+ virtual bool _canClip();
+
+ Geom::OptRect _paintbox;
+ NRStyle _nrstyle;
+
+ friend class DrawingGlyphs;
+};
+
+} // end namespace Inkscape
+
+#endif // !SEEN_INKSCAPE_DISPLAY_DRAWING_ITEM_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/drawing.cpp b/src/display/drawing.cpp
new file mode 100644
index 000000000..06183fed2
--- /dev/null
+++ b/src/display/drawing.cpp
@@ -0,0 +1,205 @@
+/**
+ * @file
+ * @brief SVG drawing for display
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2011 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <algorithm>
+#include "display/drawing.h"
+#include "nr-filter-gaussian.h"
+#include "nr-filter-types.h"
+
+namespace Inkscape {
+
+Drawing::Drawing(SPCanvasArena *arena)
+ : _root(NULL)
+ , outlinecolor(0x000000ff)
+ , delta(0)
+ , _exact(false)
+ , _rendermode(RENDERMODE_NORMAL)
+ , _colormode(COLORMODE_NORMAL)
+ , _blur_quality(BLUR_QUALITY_BEST)
+ , _filter_quality(Filters::FILTER_QUALITY_BEST)
+ , _cache_score_threshold(50000.0)
+ , _cache_budget(0)
+ , _canvasarena(arena)
+{
+
+}
+
+Drawing::~Drawing()
+{
+ delete _root;
+}
+
+void
+Drawing::setRoot(DrawingItem *item)
+{
+ delete _root;
+ _root = item;
+ if (item) {
+ assert(item->_child_type == DrawingItem::CHILD_ORPHAN);
+ item->_child_type = DrawingItem::CHILD_ROOT;
+ }
+}
+
+RenderMode
+Drawing::renderMode() const
+{
+ return _exact ? RENDERMODE_NORMAL : _rendermode;
+}
+ColorMode
+Drawing::colorMode() const
+{
+ return (outline() || _exact) ? COLORMODE_NORMAL : _colormode;
+}
+bool
+Drawing::outline() const
+{
+ return renderMode() == RENDERMODE_OUTLINE;
+}
+bool
+Drawing::renderFilters() const
+{
+ return renderMode() == RENDERMODE_NORMAL;
+}
+int
+Drawing::blurQuality() const
+{
+ if (renderMode() == RENDERMODE_NORMAL) {
+ return _exact ? BLUR_QUALITY_BEST : _blur_quality;
+ } else {
+ return BLUR_QUALITY_WORST;
+ }
+}
+int
+Drawing::filterQuality() const
+{
+ if (renderMode() == RENDERMODE_NORMAL) {
+ return _exact ? Filters::FILTER_QUALITY_BEST : _filter_quality;
+ } else {
+ return Filters::FILTER_QUALITY_WORST;
+ }
+}
+
+void
+Drawing::setRenderMode(RenderMode mode)
+{
+ _rendermode = mode;
+}
+void
+Drawing::setColorMode(ColorMode mode)
+{
+ _colormode = mode;
+}
+void
+Drawing::setBlurQuality(int q)
+{
+ _blur_quality = q;
+}
+void
+Drawing::setFilterQuality(int q)
+{
+ _filter_quality = q;
+}
+void
+Drawing::setExact(bool e)
+{
+ _exact = e;
+}
+
+Geom::OptIntRect const &
+Drawing::cacheLimit() const
+{
+ return _cache_limit;
+}
+void
+Drawing::setCacheLimit(Geom::OptIntRect const &r)
+{
+ _cache_limit = r;
+ for (std::set<DrawingItem *>::iterator i = _cached_items.begin();
+ i != _cached_items.end(); ++i)
+ {
+ (*i)->_markForUpdate(DrawingItem::STATE_CACHE, false);
+ }
+}
+void
+Drawing::setCacheBudget(size_t bytes)
+{
+ _cache_budget = bytes;
+ _pickItemsForCaching();
+}
+
+void
+Drawing::update(Geom::IntRect const &area, UpdateContext const &ctx, unsigned flags, unsigned reset)
+{
+ if (_root) {
+ _root->update(area, ctx, flags, reset);
+ }
+ // process the updated cache scores
+ _pickItemsForCaching();
+}
+
+void
+Drawing::render(DrawingContext &ct, Geom::IntRect const &area, unsigned flags)
+{
+ if (_root) {
+ _root->render(ct, area, flags);
+ }
+}
+
+DrawingItem *
+Drawing::pick(Geom::Point const &p, double delta, unsigned flags)
+{
+ if (_root) {
+ return _root->pick(p, delta, flags);
+ }
+ return NULL;
+}
+
+void
+Drawing::_pickItemsForCaching()
+{
+ // we cache the objects with the highest score until the budget is exhausted
+ _candidate_items.sort(std::greater<CacheRecord>());
+ size_t used = 0;
+ CandidateList::iterator i;
+ for (i = _candidate_items.begin(); i != _candidate_items.end(); ++i) {
+ if (used + i->cache_size > _cache_budget) break;
+ used += i->cache_size;
+ }
+
+ std::set<DrawingItem*> to_cache;
+ for (i = _candidate_items.begin(); i != _candidate_items.end(); ++i) {
+ i->item->setCached(true);
+ to_cache.insert(i->item);
+ }
+ // Everything which is now in _cached_items but not in to_cache must be uncached
+ // Note that calling setCached on an item modifies _cached_items
+ // TODO: find a way to avoid the set copy
+ std::set<DrawingItem*> to_uncache;
+ std::set_difference(_cached_items.begin(), _cached_items.end(),
+ to_cache.begin(), to_cache.end(),
+ std::inserter(to_uncache, to_uncache.end()));
+ for (std::set<DrawingItem*>::iterator j = to_uncache.begin(); j != to_uncache.end(); ++j) {
+ (*j)->setCached(false);
+ }
+}
+
+} // end namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/drawing.h b/src/display/drawing.h
new file mode 100644
index 000000000..cfba4ebe6
--- /dev/null
+++ b/src/display/drawing.h
@@ -0,0 +1,113 @@
+/**
+ * @file
+ * @brief SVG drawing for display
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2011 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_INKSCAPE_DISPLAY_DRAWING_H
+#define SEEN_INKSCAPE_DISPLAY_DRAWING_H
+
+#include <set>
+#include <boost/operators.hpp>
+#include <boost/utility.hpp>
+#include <sigc++/sigc++.h>
+#include <2geom/rect.h>
+#include "display/display-forward.h"
+#include "display/drawing-item.h"
+#include "display/rendermode.h"
+
+namespace Inkscape {
+
+class Drawing
+ : boost::noncopyable
+{
+public:
+ struct OutlineColors {
+ guint32 paths;
+ guint32 clippaths;
+ guint32 masks;
+ guint32 images;
+ };
+
+ Drawing(SPCanvasArena *arena = NULL);
+ ~Drawing();
+
+ DrawingItem *root() { return _root; }
+ SPCanvasArena *arena() { return _canvasarena; }
+ void setRoot(DrawingItem *item);
+
+ RenderMode renderMode() const;
+ ColorMode colorMode() const;
+ bool outline() const;
+ bool renderFilters() const;
+ int blurQuality() const;
+ int filterQuality() const;
+ void setRenderMode(RenderMode mode);
+ void setColorMode(ColorMode mode);
+ void setBlurQuality(int q);
+ void setFilterQuality(int q);
+ void setExact(bool e);
+
+ Geom::OptIntRect const &cacheLimit() const;
+ void setCacheLimit(Geom::OptIntRect const &r);
+ void setCacheBudget(size_t bytes);
+
+ OutlineColors const &colors() const { return _colors; }
+
+ void update(Geom::IntRect const &area = Geom::IntRect::infinite(), UpdateContext const &ctx = UpdateContext(), unsigned flags = DrawingItem::STATE_ALL, unsigned reset = 0);
+ void render(DrawingContext &ct, Geom::IntRect const &area, unsigned flags = 0);
+ DrawingItem *pick(Geom::Point const &p, double delta, unsigned flags);
+
+ sigc::signal<void, DrawingItem *> signal_request_update;
+ sigc::signal<void, Geom::IntRect const &> signal_request_render;
+ sigc::signal<void, DrawingItem *> signal_item_deleted;
+
+private:
+ void _pickItemsForCaching();
+
+ typedef std::list<CacheRecord> CandidateList;
+
+ DrawingItem *_root;
+ std::set<DrawingItem *> _cached_items; // modified by DrawingItem::setCached()
+ CacheList _candidate_items;
+public:
+ // TODO: remove these temporarily public members
+ guint32 outlinecolor;
+ double delta;
+private:
+ bool _exact; // if true then rendering must be exact
+ RenderMode _rendermode;
+ ColorMode _colormode;
+ int _blur_quality;
+ int _filter_quality;
+ Geom::OptIntRect _cache_limit;
+
+ double _cache_score_threshold; ///< do not consider objects for caching below this score
+ size_t _cache_budget; ///< maximum allowed size of cache
+
+ OutlineColors _colors;
+ SPCanvasArena *_canvasarena; // may be NULL is this arena is not the screen
+ // but used for export etc.
+
+ friend class DrawingItem;
+};
+
+} // end namespace Inkscape
+
+#endif // !SEEN_INKSCAPE_DRAWING_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/grayscale.cpp b/src/display/grayscale.cpp
index 745a08c1e..e468044d3 100644
--- a/src/display/grayscale.cpp
+++ b/src/display/grayscale.cpp
@@ -82,7 +82,7 @@ guchar luminance(guchar r, guchar g, guchar b) {
*/
bool activeDesktopIsGrayscale() {
if (SP_ACTIVE_DESKTOP) {
- return (SP_ACTIVE_DESKTOP->getColorMode() == Inkscape::COLORRENDERMODE_GRAYSCALE);
+ return (SP_ACTIVE_DESKTOP->getColorMode() == Inkscape::COLORMODE_GRAYSCALE);
} else {
return false;
}
diff --git a/src/display/nr-arena-forward.h b/src/display/nr-arena-forward.h
deleted file mode 100644
index 5a5cf228a..000000000
--- a/src/display/nr-arena-forward.h
+++ /dev/null
@@ -1,51 +0,0 @@
-#ifndef __NR_ARENA_FORWARD_H__
-#define __NR_ARENA_FORWARD_H__
-
-/*
- * RGBA display list system for inkscape
- *
- * Author:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * Copyright (C) 2001-2002 Lauris Kaplinski
- * Copyright (C) 2001 Ximian, Inc.
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-struct NRArena;
-struct NRArenaClass;
-
-struct NRArenaItem;
-struct NRArenaItemClass;
-
-struct NRArenaGroup;
-struct NRArenaGroupClass;
-
-struct NRArenaShape;
-struct NRArenaShapeClass;
-
-struct NRArenaShapeGroup;
-struct NRArenaShapeGroupClass;
-
-struct NRArenaImage;
-struct NRArenaImageClass;
-
-struct NRArenaGlyphs;
-struct NRArenaGlyphsClass;
-
-struct NRArenaGlyphsGroup;
-struct NRArenaGlyphsGroupClass;
-
-#endif
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/nr-arena-glyphs.cpp b/src/display/nr-arena-glyphs.cpp
deleted file mode 100644
index d09f66a2f..000000000
--- a/src/display/nr-arena-glyphs.cpp
+++ /dev/null
@@ -1,476 +0,0 @@
-/*
- * RGBA display list system for inkscape
- *
- * Author:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * Copyright (C) 2002 Lauris Kaplinski
- *
- * Released under GNU GPL
- *
- */
-
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-#include "libnr/nr-convert2geom.h"
-#include <2geom/affine.h>
-#include "style.h"
-#include "display/nr-arena.h"
-#include "display/nr-arena-glyphs.h"
-#include <cairo.h>
-#include "display/cairo-utils.h"
-#include "helper/geom.h"
-
-#ifdef test_glyph_liv
-#include "../display/canvas-bpath.h"
-#include "libnrtype/font-instance.h"
-
-// defined in nr-arena-shape.cpp
-void nr_pixblock_render_shape_mask_or(NRPixBlock &m, Shape *theS);
-#endif
-
-#ifdef ENABLE_SVG_FONTS
-#include "nr-svgfonts.h"
-#endif //#ifdef ENABLE_SVG_FONTS
-
-static void nr_arena_glyphs_class_init(NRArenaGlyphsClass *klass);
-static void nr_arena_glyphs_init(NRArenaGlyphs *glyphs);
-static void nr_arena_glyphs_finalize(NRObject *object);
-
-static guint nr_arena_glyphs_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, guint reset);
-static guint nr_arena_glyphs_clip(cairo_t *ct, NRArenaItem *item, NRRectL *area);
-static NRArenaItem *nr_arena_glyphs_pick(NRArenaItem *item, Geom::Point p, double delta, unsigned int sticky);
-
-static NRArenaItemClass *glyphs_parent_class;
-
-NRType
-nr_arena_glyphs_get_type(void)
-{
- static NRType type = 0;
- if (!type) {
- type = nr_object_register_type(NR_TYPE_ARENA_ITEM,
- "NRArenaGlyphs",
- sizeof(NRArenaGlyphsClass),
- sizeof(NRArenaGlyphs),
- (void (*)(NRObjectClass *)) nr_arena_glyphs_class_init,
- (void (*)(NRObject *)) nr_arena_glyphs_init);
- }
- return type;
-}
-
-static void
-nr_arena_glyphs_class_init(NRArenaGlyphsClass *klass)
-{
- NRObjectClass *object_class;
- NRArenaItemClass *item_class;
-
- object_class = (NRObjectClass *) klass;
- item_class = (NRArenaItemClass *) klass;
-
- glyphs_parent_class = (NRArenaItemClass *) ((NRObjectClass *) klass)->parent;
-
- object_class->finalize = nr_arena_glyphs_finalize;
- object_class->cpp_ctor = NRObject::invoke_ctor<NRArenaGlyphs>;
-
- item_class->update = nr_arena_glyphs_update;
- item_class->clip = nr_arena_glyphs_clip;
- item_class->pick = nr_arena_glyphs_pick;
-}
-
-static void
-nr_arena_glyphs_init(NRArenaGlyphs *glyphs)
-{
- glyphs->g_transform.setIdentity();
- glyphs->font = NULL;
- glyphs->glyph = 0;
- glyphs->x = glyphs->y = 0.0;
-}
-
-static void
-nr_arena_glyphs_finalize(NRObject *object)
-{
- NRArenaGlyphs *glyphs = static_cast<NRArenaGlyphs *>(object);
-
- if (glyphs->font) {
- glyphs->font->Unref();
- glyphs->font=NULL;
- }
-
- ((NRObjectClass *) glyphs_parent_class)->finalize(object);
-}
-
-static guint
-nr_arena_glyphs_update(NRArenaItem *item, NRRectL */*area*/, NRGC *gc, guint /*state*/, guint /*reset*/)
-{
- NRArenaGlyphs *glyphs = NR_ARENA_GLYPHS(item);
- NRArenaGlyphsGroup *ggroup = NR_ARENA_GLYPHS_GROUP(item->parent);
-
- if (!glyphs->font || !ggroup->style)
- return NR_ARENA_ITEM_STATE_ALL;
- if (ggroup->nrstyle.fill.type == NRStyle::PAINT_NONE && ggroup->nrstyle.stroke.type == NRStyle::PAINT_NONE)
- return NR_ARENA_ITEM_STATE_ALL;
-
- Geom::OptRect b;
- Geom::Affine t = glyphs->g_transform * gc->transform;
- glyphs->x = t[4];
- glyphs->y = t[5];
-
- b = bounds_exact_transformed(*glyphs->font->PathVector(glyphs->glyph), t);
- if (b && ggroup->nrstyle.stroke.type != NRStyle::PAINT_NONE) {
- float width, scale;
- scale = gc->transform.descrim();
- width = MAX(0.125, ggroup->nrstyle.stroke_width * scale);
- if ( fabs(ggroup->nrstyle.stroke_width * scale) > 0.01 ) { // FIXME: this is always true
- b->expandBy(width);
- }
- // those pesky miters, now
- float miterMax = width * ggroup->nrstyle.miter_limit;
- if ( miterMax > 0.01 ) {
- // grunt mode. we should compute the various miters instead
- // (one for each point on the curve)
- b->expandBy(miterMax);
- }
- }
-
- if (b) {
- item->bbox.x0 = floor(b->left());
- item->bbox.y0 = floor(b->top());
- item->bbox.x1 = ceil (b->right());
- item->bbox.y1 = ceil (b->bottom());
- } else {
- item->bbox.x0 = 0;
- item->bbox.y0 = 0;
- item->bbox.x1 = -1;
- item->bbox.y1 = -1;
- }
-
- return NR_ARENA_ITEM_STATE_ALL;
-}
-
-static guint nr_arena_glyphs_clip(cairo_t * /*ct*/, NRArenaItem *item, NRRectL * /*area*/)
-{
- NRArenaGlyphs *glyphs;
-
- glyphs = NR_ARENA_GLYPHS(item);
-
- if (!glyphs->font) return item->state;
-
- // TODO : render to greyscale pixblock provided for clipping
-
- return item->state;
-}
-
-static NRArenaItem *
-nr_arena_glyphs_pick(NRArenaItem *item, Geom::Point p, gdouble delta, unsigned int /*sticky*/)
-{
- NRArenaGlyphs *glyphs;
-
- glyphs = NR_ARENA_GLYPHS(item);
-
- if (!glyphs->font ) return NULL;
-
- double const x = p[Geom::X];
- double const y = p[Geom::Y];
- /* With text we take a simple approach: pick if the point is in a characher bbox */
- if ((x + delta >= item->bbox.x0) && (y + delta >= item->bbox.y0) && (x - delta <= item->bbox.x1) && (y - delta <= item->bbox.y1)) return item;
-
- return NULL;
-}
-
-void
-nr_arena_glyphs_set_path(NRArenaGlyphs *glyphs, SPCurve */*curve*/, unsigned int /*lieutenant*/, font_instance *font, gint glyph, Geom::Affine const *transform)
-{
- nr_return_if_fail(glyphs != NULL);
- nr_return_if_fail(NR_IS_ARENA_GLYPHS(glyphs));
-
- nr_arena_item_request_render(NR_ARENA_ITEM(glyphs));
-
- if (transform) {
- glyphs->g_transform = *transform;
- } else {
- glyphs->g_transform.setIdentity();
- }
-
- if (font) font->Ref();
- if (glyphs->font) glyphs->font->Unref();
- glyphs->font=font;
- glyphs->glyph = glyph;
-
- nr_arena_item_request_update(NR_ARENA_ITEM(glyphs), NR_ARENA_ITEM_STATE_ALL, FALSE);
-}
-
-static void nr_arena_glyphs_group_class_init(NRArenaGlyphsGroupClass *klass);
-static void nr_arena_glyphs_group_init(NRArenaGlyphsGroup *group);
-static void nr_arena_glyphs_group_finalize(NRObject *object);
-
-static guint nr_arena_glyphs_group_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, guint reset);
-static unsigned int nr_arena_glyphs_group_render(cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int flags);
-static unsigned int nr_arena_glyphs_group_clip(cairo_t *ct, NRArenaItem *item, NRRectL *area);
-static NRArenaItem *nr_arena_glyphs_group_pick(NRArenaItem *item, Geom::Point p, gdouble delta, unsigned int sticky);
-
-static NRArenaGroupClass *group_parent_class;
-
-NRType
-nr_arena_glyphs_group_get_type(void)
-{
- static NRType type = 0;
- if (!type) {
- type = nr_object_register_type(NR_TYPE_ARENA_GROUP,
- "NRArenaGlyphsGroup",
- sizeof(NRArenaGlyphsGroupClass),
- sizeof(NRArenaGlyphsGroup),
- (void (*)(NRObjectClass *)) nr_arena_glyphs_group_class_init,
- (void (*)(NRObject *)) nr_arena_glyphs_group_init);
- }
- return type;
-}
-
-static void
-nr_arena_glyphs_group_class_init(NRArenaGlyphsGroupClass *klass)
-{
- NRObjectClass *object_class;
- NRArenaItemClass *item_class;
-
- object_class = (NRObjectClass *) klass;
- item_class = (NRArenaItemClass *) klass;
-
- group_parent_class = (NRArenaGroupClass *) ((NRObjectClass *) klass)->parent;
-
- object_class->finalize = nr_arena_glyphs_group_finalize;
- object_class->cpp_ctor = NRObject::invoke_ctor<NRArenaGlyphsGroup>;
-
- item_class->update = nr_arena_glyphs_group_update;
- item_class->render = nr_arena_glyphs_group_render;
- item_class->clip = nr_arena_glyphs_group_clip;
- item_class->pick = nr_arena_glyphs_group_pick;
-}
-
-static void
-nr_arena_glyphs_group_init(NRArenaGlyphsGroup *group)
-{
- group->style = NULL;
- group->paintbox.x0 = group->paintbox.y0 = 0.0F;
- group->paintbox.x1 = group->paintbox.y1 = -1.0F;
-}
-
-static void
-nr_arena_glyphs_group_finalize(NRObject *object)
-{
- NRArenaGlyphsGroup *group=static_cast<NRArenaGlyphsGroup *>(object);
-
- if (group->style) {
- sp_style_unref(group->style);
- group->style = NULL;
- }
-
- ((NRObjectClass *) group_parent_class)->finalize(object);
-}
-
-static guint
-nr_arena_glyphs_group_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, guint reset)
-{
- NRArenaGlyphsGroup *group = NR_ARENA_GLYPHS_GROUP(item);
-
- group->nrstyle.update();
-
- if (((NRArenaItemClass *) group_parent_class)->update)
- return ((NRArenaItemClass *) group_parent_class)->update(item, area, gc, state, reset);
-
- return NR_ARENA_ITEM_STATE_ALL;
-}
-
-
-static unsigned int
-nr_arena_glyphs_group_render(cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock * /*pb*/, unsigned int /*flags*/)
-{
- NRArenaItem *child = 0;
-
- NRArenaGroup *group = NR_ARENA_GROUP(item);
- NRArenaGlyphsGroup *ggroup = NR_ARENA_GLYPHS_GROUP(item);
-
- if (!ct) {
- return item->state;
- }
-
- if (item->arena->rendermode == Inkscape::RENDERMODE_OUTLINE) {
- cairo_save(ct);
- guint32 rgba = item->arena->outlinecolor;
- ink_cairo_set_source_rgba32(ct, rgba);
- cairo_set_tolerance(ct, 1.25); // low quality, but good enough for outline mode
- cairo_new_path(ct);
- ink_cairo_transform(ct, ggroup->ctm);
-
- for (child = group->children; child != NULL; child = child->next) {
- NRArenaGlyphs *g = NR_ARENA_GLYPHS(child);
-
- Geom::PathVector const * pathv = g->font->PathVector(g->glyph);
- Geom::Affine transform = g->g_transform;
-
- cairo_save(ct);
- ink_cairo_transform(ct, transform);
- feed_pathvector_to_cairo (ct, *pathv);
- cairo_fill(ct);
- cairo_restore(ct);
- }
- cairo_restore(ct);
- return item->state;
- }
-
- // NOTE: this is very similar to nr-arena-shape.cpp; the only difference is path feeding
- bool has_stroke, has_fill;
-
- cairo_save(ct);
- ink_cairo_transform(ct, ggroup->ctm);
-
- has_fill = ggroup->nrstyle.prepareFill(ct, &ggroup->paintbox);
- has_stroke = ggroup->nrstyle.prepareStroke(ct, &ggroup->paintbox);
-
- if (has_fill || has_stroke) {
- for (NRArenaItem *child = ggroup->children; child != NULL; child = child->next) {
- NRArenaGlyphs *g = NR_ARENA_GLYPHS(child);
- Geom::PathVector const &pathv = *g->font->PathVector(g->glyph);
-
- cairo_save(ct);
- ink_cairo_transform(ct, g->g_transform);
- feed_pathvector_to_cairo(ct, pathv);
- cairo_restore(ct);
- }
-
- if (has_fill) {
- ggroup->nrstyle.applyFill(ct);
- cairo_fill_preserve(ct);
- }
- if (has_stroke) {
- ggroup->nrstyle.applyStroke(ct);
- cairo_stroke_preserve(ct);
- }
- cairo_new_path(ct); // clear path
- } // has fill or stroke pattern
- cairo_restore(ct);
-
- return item->state;
-}
-
-static unsigned int nr_arena_glyphs_group_clip(cairo_t *ct, NRArenaItem *item, NRRectL * /*area*/)
-{
- NRArenaGroup *ggroup = NR_ARENA_GLYPHS_GROUP(item);
-
- cairo_save(ct);
- // handle clip-rule
- if (ggroup->style) {
- if (ggroup->style->clip_rule.computed == SP_WIND_RULE_EVENODD) {
- cairo_set_fill_rule(ct, CAIRO_FILL_RULE_EVEN_ODD);
- } else {
- cairo_set_fill_rule(ct, CAIRO_FILL_RULE_WINDING);
- }
- }
- ink_cairo_transform(ct, ggroup->ctm);
-
- for (NRArenaItem *child = ggroup->children; child != NULL; child = child->next) {
- NRArenaGlyphs *g = NR_ARENA_GLYPHS(child);
- Geom::PathVector const &pathv = *g->font->PathVector(g->glyph);
-
- cairo_save(ct);
- ink_cairo_transform(ct, g->g_transform);
- feed_pathvector_to_cairo(ct, pathv);
- cairo_restore(ct);
- }
- cairo_fill(ct);
- cairo_restore(ct);
-
- return item->state;
-}
-
-static NRArenaItem *
-nr_arena_glyphs_group_pick(NRArenaItem *item, Geom::Point p, gdouble delta, unsigned int sticky)
-{
- NRArenaItem *picked = NULL;
-
- if (((NRArenaItemClass *) group_parent_class)->pick)
- picked = ((NRArenaItemClass *) group_parent_class)->pick(item, p, delta, sticky);
-
- if (picked) picked = item;
-
- return picked;
-}
-
-void
-nr_arena_glyphs_group_clear(NRArenaGlyphsGroup *sg)
-{
- NRArenaGroup *group = NR_ARENA_GROUP(sg);
-
- nr_arena_item_request_render(NR_ARENA_ITEM(group));
-
- while (group->children) {
- nr_arena_item_remove_child(NR_ARENA_ITEM(group), group->children);
- }
-}
-
-void
-nr_arena_glyphs_group_add_component(NRArenaGlyphsGroup *sg, font_instance *font, int glyph, Geom::Affine const &transform)
-{
- NRArenaGroup *group;
-
- group = NR_ARENA_GROUP(sg);
-
- Geom::PathVector const * pathv = ( font
- ? font->PathVector(glyph)
- : NULL );
- if ( pathv ) {
- nr_arena_item_request_render(NR_ARENA_ITEM(group));
-
- NRArenaItem *new_arena = NRArenaGlyphs::create(group->arena);
- nr_arena_item_append_child(NR_ARENA_ITEM(group), new_arena);
- nr_arena_item_unref(new_arena);
- nr_arena_glyphs_set_path(NR_ARENA_GLYPHS(new_arena), NULL, FALSE, font, glyph, &transform);
- }
-}
-
-void
-nr_arena_glyphs_group_set_style(NRArenaGlyphsGroup *sg, SPStyle *style)
-{
- nr_return_if_fail(sg != NULL);
- nr_return_if_fail(NR_IS_ARENA_GLYPHS_GROUP(sg));
-
- if (style) sp_style_ref(style);
- if (sg->style) sp_style_unref(sg->style);
- sg->style = style;
-
- sg->nrstyle.set(style);
-
- nr_arena_item_request_update(NR_ARENA_ITEM(sg), NR_ARENA_ITEM_STATE_ALL, FALSE);
-}
-
-void
-nr_arena_glyphs_group_set_paintbox(NRArenaGlyphsGroup *gg, NRRect const *pbox)
-{
- nr_return_if_fail(gg != NULL);
- nr_return_if_fail(NR_IS_ARENA_GLYPHS_GROUP(gg));
- nr_return_if_fail(pbox != NULL);
-
- if ((pbox->x0 < pbox->x1) && (pbox->y0 < pbox->y1)) {
- gg->paintbox.x0 = pbox->x0;
- gg->paintbox.y0 = pbox->y0;
- gg->paintbox.x1 = pbox->x1;
- gg->paintbox.y1 = pbox->y1;
- } else {
- gg->paintbox.x0 = gg->paintbox.y0 = 0.0F;
- gg->paintbox.x1 = gg->paintbox.y1 = -1.0F;
- }
-
- nr_arena_item_request_update(NR_ARENA_ITEM(gg), NR_ARENA_ITEM_STATE_ALL, FALSE);
-}
-
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/nr-arena-glyphs.h b/src/display/nr-arena-glyphs.h
deleted file mode 100644
index c43095cb2..000000000
--- a/src/display/nr-arena-glyphs.h
+++ /dev/null
@@ -1,108 +0,0 @@
-#ifndef SEEN_NR_ARENA_GLYPHS_H
-#define SEEN_NR_ARENA_GLYPHS_H
-
-/*
- * RGBA display list system for inkscape
- *
- * Author:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * Copyright (C) 2002 Lauris Kaplinski
- *
- * Released under GNU GPL
- *
- */
-
-#define NR_TYPE_ARENA_GLYPHS (nr_arena_glyphs_get_type ())
-#define NR_ARENA_GLYPHS(obj) (NR_CHECK_INSTANCE_CAST ((obj), NR_TYPE_ARENA_GLYPHS, NRArenaGlyphs))
-#define NR_IS_ARENA_GLYPHS(obj) (NR_CHECK_INSTANCE_TYPE ((obj), NR_TYPE_ARENA_GLYPHS))
-
-#include "libnrtype/nrtype-forward.h"
-#include "display/display-forward.h"
-#include "forward.h"
-#include "display/nr-arena-item.h"
-#include "display/nr-style.h"
-
-#define test_glyph_liv
-
-struct SPCurve;
-class Shape;
-class SPPainter;
-
-NRType nr_arena_glyphs_get_type (void);
-
-struct NRArenaGlyphs : public NRArenaItem {
- /* Glyphs data */
- Geom::Affine g_transform;
-
- font_instance *font;
- gint glyph;
- float x, y;
-
- static NRArenaGlyphs *create(NRArena *arena) {
- NRArenaGlyphs *obj=reinterpret_cast<NRArenaGlyphs *>(nr_object_new(NR_TYPE_ARENA_GLYPHS));
- obj->init(arena);
- return obj;
- }
-};
-
-struct NRArenaGlyphsClass {
- NRArenaItemClass parent_class;
-};
-
-void nr_arena_glyphs_set_path ( NRArenaGlyphs *glyphs,
- SPCurve *curve, unsigned int lieutenant,
- font_instance *font, int glyph,
- Geom::Affine const *transform );
-void nr_arena_glyphs_set_style (NRArenaGlyphs *glyphs, SPStyle *style);
-
-/* Integrated group of component glyphss */
-
-typedef struct NRArenaGlyphsGroup NRArenaGlyphsGroup;
-typedef struct NRArenaGlyphsGroupClass NRArenaGlyphsGroupClass;
-
-#include "nr-arena-group.h"
-
-#define NR_TYPE_ARENA_GLYPHS_GROUP (nr_arena_glyphs_group_get_type ())
-#define NR_ARENA_GLYPHS_GROUP(obj) (NR_CHECK_INSTANCE_CAST ((obj), NR_TYPE_ARENA_GLYPHS_GROUP, NRArenaGlyphsGroup))
-#define NR_IS_ARENA_GLYPHS_GROUP(obj) (NR_CHECK_INSTANCE_TYPE ((obj), NR_TYPE_ARENA_GLYPHS_GROUP))
-
-NRType nr_arena_glyphs_group_get_type (void);
-
-struct NRArenaGlyphsGroup : public NRArenaGroup {
- NRRect paintbox;
- NRStyle nrstyle;
-
- static NRArenaGlyphsGroup *create(NRArena *arena) {
- NRArenaGlyphsGroup *obj=reinterpret_cast<NRArenaGlyphsGroup *>(nr_object_new(NR_TYPE_ARENA_GLYPHS_GROUP));
- obj->init(arena);
- return obj;
- }
-};
-
-struct NRArenaGlyphsGroupClass {
- NRArenaGroupClass parent_class;
-};
-
-/* Utility functions */
-
-void nr_arena_glyphs_group_clear (NRArenaGlyphsGroup *group);
-
-void nr_arena_glyphs_group_add_component (NRArenaGlyphsGroup *group, font_instance *font, int glyph, Geom::Affine const &transform);
-
-void nr_arena_glyphs_group_set_style (NRArenaGlyphsGroup *group, SPStyle *style);
-
-void nr_arena_glyphs_group_set_paintbox (NRArenaGlyphsGroup *group, const NRRect *pbox);
-
-#endif // SEEN_NR_ARENA_GLYPHS_H
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/display/nr-arena-group.cpp b/src/display/nr-arena-group.cpp
deleted file mode 100644
index 1d552fbc2..000000000
--- a/src/display/nr-arena-group.cpp
+++ /dev/null
@@ -1,299 +0,0 @@
-#define __NR_ARENA_GROUP_C__
-
-/*
- * RGBA display list system for inkscape
- *
- * Author:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * Copyright (C) 2001-2002 Lauris Kaplinski
- * Copyright (C) 2001 Ximian, Inc.
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include "display/canvas-bpath.h"
-#include "display/nr-arena.h"
-#include "display/nr-arena-group.h"
-#include "display/nr-filter.h"
-#include "display/nr-filter-types.h"
-#include "display/rendermode.h"
-#include "style.h"
-#include "sp-filter.h"
-#include "sp-filter-reference.h"
-#include "filters/blend.h"
-#include "display/nr-filter-blend.h"
-#include "helper/geom.h"
-
-static void nr_arena_group_class_init (NRArenaGroupClass *klass);
-static void nr_arena_group_init (NRArenaGroup *group);
-
-static NRArenaItem *nr_arena_group_children (NRArenaItem *item);
-static NRArenaItem *nr_arena_group_last_child (NRArenaItem *item);
-static void nr_arena_group_add_child (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref);
-static void nr_arena_group_remove_child (NRArenaItem *item, NRArenaItem *child);
-static void nr_arena_group_set_child_position (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref);
-
-static unsigned int nr_arena_group_update (NRArenaItem *item, NRRectL *area, NRGC *gc, unsigned int state, unsigned int reset);
-static unsigned int nr_arena_group_render (cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int flags);
-static unsigned int nr_arena_group_clip (cairo_t *ct, NRArenaItem *item, NRRectL *area);
-static NRArenaItem *nr_arena_group_pick (NRArenaItem *item, Geom::Point p, double delta, unsigned int sticky);
-
-static NRArenaItemClass *parent_class;
-
-NRType
-nr_arena_group_get_type (void)
-{
- static NRType type = 0;
- if (!type) {
- type = nr_object_register_type (NR_TYPE_ARENA_ITEM,
- "NRArenaGroup",
- sizeof (NRArenaGroupClass),
- sizeof (NRArenaGroup),
- (void (*) (NRObjectClass *)) nr_arena_group_class_init,
- (void (*) (NRObject *)) nr_arena_group_init);
- }
- return type;
-}
-
-static void
-nr_arena_group_class_init (NRArenaGroupClass *klass)
-{
- NRObjectClass *object_class;
- NRArenaItemClass *item_class;
-
- object_class = (NRObjectClass *) klass;
- item_class = (NRArenaItemClass *) klass;
-
- parent_class = (NRArenaItemClass *) ((NRObjectClass *) klass)->parent;
-
- object_class->cpp_ctor = NRObject::invoke_ctor<NRArenaGroup>;
-
- item_class->children = nr_arena_group_children;
- item_class->last_child = nr_arena_group_last_child;
- item_class->add_child = nr_arena_group_add_child;
- item_class->set_child_position = nr_arena_group_set_child_position;
- item_class->remove_child = nr_arena_group_remove_child;
- item_class->update = nr_arena_group_update;
- item_class->render = nr_arena_group_render;
- item_class->clip = nr_arena_group_clip;
- item_class->pick = nr_arena_group_pick;
-}
-
-static void
-nr_arena_group_init (NRArenaGroup *group)
-{
- group->transparent = FALSE;
- group->children = NULL;
- group->last = NULL;
- group->style = NULL;
- group->child_transform.setIdentity();
-}
-
-static NRArenaItem *
-nr_arena_group_children (NRArenaItem *item)
-{
- NRArenaGroup *group = NR_ARENA_GROUP (item);
-
- return group->children;
-}
-
-static NRArenaItem *
-nr_arena_group_last_child (NRArenaItem *item)
-{
- NRArenaGroup *group = NR_ARENA_GROUP (item);
-
- return group->last;
-}
-
-static void
-nr_arena_group_add_child (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref)
-{
- NRArenaGroup *group = NR_ARENA_GROUP (item);
-
- if (!ref) {
- group->children = nr_arena_item_attach (item, child, NULL, group->children);
- } else {
- ref->next = nr_arena_item_attach (item, child, ref, ref->next);
- }
-
- if (ref == group->last) group->last = child;
-
- nr_arena_item_request_update (item, NR_ARENA_ITEM_STATE_ALL, FALSE);
-}
-
-static void
-nr_arena_group_remove_child (NRArenaItem *item, NRArenaItem *child)
-{
- NRArenaGroup *group = NR_ARENA_GROUP (item);
-
- if (child == group->last) group->last = child->prev;
-
- if (child->prev) {
- nr_arena_item_detach (item, child);
- } else {
- group->children = nr_arena_item_detach (item, child);
- }
-
- nr_arena_item_request_update (item, NR_ARENA_ITEM_STATE_ALL, FALSE);
-}
-
-static void
-nr_arena_group_set_child_position (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref)
-{
- NRArenaGroup *group = NR_ARENA_GROUP (item);
-
- if (child == group->last) group->last = child->prev;
-
- if (child->prev) {
- nr_arena_item_detach (item, child);
- } else {
- group->children = nr_arena_item_detach (item, child);
- }
-
- if (!ref) {
- group->children = nr_arena_item_attach (item, child, NULL, group->children);
- } else {
- ref->next = nr_arena_item_attach (item, child, ref, ref->next);
- }
-
- if (ref == group->last) group->last = child;
-
- nr_arena_item_request_render (child);
-}
-
-static unsigned int
-nr_arena_group_update (NRArenaItem *item, NRRectL *area, NRGC *gc, unsigned int state, unsigned int reset)
-{
- unsigned int newstate;
- NRArenaGroup *group = NR_ARENA_GROUP (item);
- unsigned int beststate = NR_ARENA_ITEM_STATE_ALL;
- bool outline = (item->arena->rendermode == Inkscape::RENDERMODE_OUTLINE);
-
- for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
- NRGC cgc(gc);
- cgc.transform = group->child_transform * gc->transform;
- newstate = nr_arena_item_invoke_update (child, area, &cgc, state, reset);
- beststate = beststate & newstate;
- }
-
- if (beststate & NR_ARENA_ITEM_STATE_BBOX) {
- item->bbox = NR_RECT_L_EMPTY;
- for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
- if (child->visible)
- nr_rect_l_union (&item->bbox, &item->bbox, outline ? &child->bbox : &child->drawbox);
- }
- }
-
- return beststate;
-}
-
-void nr_arena_group_set_style (NRArenaGroup *group, SPStyle *style)
-{
- g_return_if_fail(group != NULL);
- g_return_if_fail(NR_IS_ARENA_GROUP(group));
-
- if (style) sp_style_ref(style);
- if (group->style) sp_style_unref(group->style);
- group->style = style;
-
- //if group has a filter
- if (style->filter.set && style->getFilter()) {
- if (!group->filter) {
- int primitives = sp_filter_primitive_count(SP_FILTER(style->getFilter()));
- group->filter = new Inkscape::Filters::Filter(primitives);
- }
- sp_filter_build_renderer(SP_FILTER(style->getFilter()), group->filter);
- } else {
- //no filter set for this group
- delete group->filter;
- group->filter = NULL;
- }
-
- if (style && style->enable_background.set
- && style->enable_background.value == SP_CSS_BACKGROUND_NEW) {
- group->background_new = true;
- }
-}
-
-static unsigned int
-nr_arena_group_render (cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int flags)
-{
- NRArenaGroup *group = NR_ARENA_GROUP (item);
-
- unsigned int ret = item->state;
-
- /* Just compose children into parent buffer */
- for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
- ret = nr_arena_item_invoke_render (ct, child, area, pb, flags);
- if (ret & NR_ARENA_ITEM_STATE_INVALID) break;
- }
-
- return ret;
-}
-
-static unsigned int
-nr_arena_group_clip (cairo_t *ct, NRArenaItem *item, NRRectL *area)
-{
- NRArenaGroup *group = NR_ARENA_GROUP (item);
- unsigned int ret = item->state;
-
- for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
- ret = nr_arena_item_invoke_clip (ct, child, area);
- if (ret & NR_ARENA_ITEM_STATE_INVALID) break;
- }
-
- return ret;
-}
-
-static NRArenaItem *
-nr_arena_group_pick (NRArenaItem *item, Geom::Point p, double delta, unsigned int sticky)
-{
- NRArenaGroup *group = NR_ARENA_GROUP (item);
-
- for (NRArenaItem *child = group->last; child != NULL; child = child->prev) {
- NRArenaItem *picked = nr_arena_item_invoke_pick (child, p, delta, sticky);
- if (picked)
- return (group->transparent) ? picked : item;
- }
-
- return NULL;
-}
-
-void
-nr_arena_group_set_transparent (NRArenaGroup *group, unsigned int transparent)
-{
- nr_return_if_fail (group != NULL);
- nr_return_if_fail (NR_IS_ARENA_GROUP (group));
-
- group->transparent = transparent;
-}
-
-void nr_arena_group_set_child_transform(NRArenaGroup *group, Geom::Affine const &t)
-{
- Geom::Affine nt(t);
- nr_arena_group_set_child_transform(group, &nt);
-}
-
-void nr_arena_group_set_child_transform(NRArenaGroup *group, Geom::Affine const *t)
-{
- if (!t) t = &GEOM_MATRIX_IDENTITY;
-
- if (!Geom::matrix_equalp(*t, group->child_transform, NR_EPSILON)) {
- nr_arena_item_request_render (NR_ARENA_ITEM (group));
- group->child_transform = *t;
- nr_arena_item_request_update (NR_ARENA_ITEM (group), NR_ARENA_ITEM_STATE_ALL, TRUE);
- }
-}
-
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/nr-arena-group.h b/src/display/nr-arena-group.h
deleted file mode 100644
index 58394643c..000000000
--- a/src/display/nr-arena-group.h
+++ /dev/null
@@ -1,61 +0,0 @@
-#ifndef __NR_ARENA_GROUP_H__
-#define __NR_ARENA_GROUP_H__
-
-/*
- * RGBA display list system for inkscape
- *
- * Author:
- * Lauris Kaplinski <lauris@ximian.com>
- *
- * Copyright (C) 2001 Lauris Kaplinski and Ximian, Inc.
- *
- * Released under GNU GPL
- *
- */
-
-#define NR_TYPE_ARENA_GROUP (nr_arena_group_get_type ())
-#define NR_ARENA_GROUP(o) (NR_CHECK_INSTANCE_CAST ((o), NR_TYPE_ARENA_GROUP, NRArenaGroup))
-#define NR_IS_ARENA_GROUP(o) (NR_CHECK_INSTANCE_TYPE ((o), NR_TYPE_ARENA_GROUP))
-
-#include "nr-arena-item.h"
-#include "style.h"
-
-NRType nr_arena_group_get_type (void);
-
-struct NRArenaGroup : public NRArenaItem{
- unsigned int transparent : 1;
- NRArenaItem *children;
- NRArenaItem *last;
- Geom::Affine child_transform;
- SPStyle *style;
-
- static NRArenaGroup *create(NRArena *arena) {
- NRArenaGroup *obj = reinterpret_cast<NRArenaGroup *>(nr_object_new(NR_TYPE_ARENA_GROUP));
- obj->init(arena);
- return obj;
- }
-};
-
-struct NRArenaGroupClass {
- NRArenaItemClass parent_class;
-};
-
-void nr_arena_group_set_transparent(NRArenaGroup *group, unsigned int transparent);
-
-void nr_arena_group_set_child_transform(NRArenaGroup *group, Geom::Affine const &t);
-void nr_arena_group_set_child_transform(NRArenaGroup *group, Geom::Affine const *t);
-void nr_arena_group_set_style(NRArenaGroup *group, SPStyle *style);
-
-#endif
-
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/nr-arena-image.cpp b/src/display/nr-arena-image.cpp
deleted file mode 100644
index a943a6214..000000000
--- a/src/display/nr-arena-image.cpp
+++ /dev/null
@@ -1,408 +0,0 @@
-#define __NR_ARENA_IMAGE_C__
-
-/*
- * RGBA display list system for inkscape
- *
- * Author:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * Copyright (C) 2001-2002 Lauris Kaplinski
- * Copyright (C) 2001 Ximian, Inc.
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include <2geom/transforms.h>
-#include "../preferences.h"
-#include "nr-arena-image.h"
-#include "style.h"
-#include "display/cairo-utils.h"
-#include "display/nr-arena.h"
-#include "display/nr-filter.h"
-#include "sp-filter.h"
-#include "sp-filter-reference.h"
-
-int nr_arena_image_x_sample = 1;
-int nr_arena_image_y_sample = 1;
-
-/*
- * NRArenaCanvasImage
- *
- */
-
-static void nr_arena_image_class_init (NRArenaImageClass *klass);
-static void nr_arena_image_init (NRArenaImage *image);
-static void nr_arena_image_finalize (NRObject *object);
-
-static unsigned int nr_arena_image_update (NRArenaItem *item, NRRectL *area, NRGC *gc, unsigned int state, unsigned int reset);
-static unsigned int nr_arena_image_render (cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int flags);
-static NRArenaItem *nr_arena_image_pick (NRArenaItem *item, Geom::Point p, double delta, unsigned int sticky);
-static Geom::Rect nr_arena_image_rect (NRArenaImage *image);
-
-static NRArenaItemClass *parent_class;
-
-NRType
-nr_arena_image_get_type (void)
-{
- static NRType type = 0;
- if (!type) {
- type = nr_object_register_type (NR_TYPE_ARENA_ITEM,
- "NRArenaImage",
- sizeof (NRArenaImageClass),
- sizeof (NRArenaImage),
- (void (*) (NRObjectClass *)) nr_arena_image_class_init,
- (void (*) (NRObject *)) nr_arena_image_init);
- }
- return type;
-}
-
-static void
-nr_arena_image_class_init (NRArenaImageClass *klass)
-{
- NRObjectClass *object_class;
- NRArenaItemClass *item_class;
-
- object_class = (NRObjectClass *) klass;
- item_class = (NRArenaItemClass *) klass;
-
- parent_class = (NRArenaItemClass *) ((NRObjectClass *) klass)->parent;
-
- object_class->finalize = nr_arena_image_finalize;
- object_class->cpp_ctor = NRObject::invoke_ctor<NRArenaImage>;
-
- item_class->update = nr_arena_image_update;
- item_class->render = nr_arena_image_render;
- item_class->pick = nr_arena_image_pick;
-}
-
-static void
-nr_arena_image_init (NRArenaImage *image)
-{
- image->pixbuf = NULL;
- image->ctm.setIdentity();
- image->clipbox = Geom::Rect();
- image->ox = image->oy = 0.0;
- image->sx = image->sy = 1.0;
-
- image->style = 0;
- image->render_opacity = TRUE;
-}
-
-static void
-nr_arena_image_finalize (NRObject *object)
-{
- NRArenaImage *image = NR_ARENA_IMAGE (object);
-
- if (image->pixbuf != NULL) {
- g_object_unref(image->pixbuf);
- cairo_surface_destroy(image->surface);
- }
- if (image->style)
- sp_style_unref(image->style);
-
- ((NRObjectClass *) parent_class)->finalize (object);
-}
-
-static unsigned int
-nr_arena_image_update( NRArenaItem *item, NRRectL */*area*/, NRGC *gc, unsigned int /*state*/, unsigned int /*reset*/ )
-{
- // clear old bbox
- nr_arena_item_request_render(item);
-
- NRArenaImage *image = NR_ARENA_IMAGE (item);
-
- /* Copy affine */
- image->ctm = gc->transform;
-
- /* Calculate bbox */
- if (image->pixbuf) {
- NRRect bbox;
-
- Geom::Rect r = nr_arena_image_rect(image) * gc->transform;
-
- item->bbox.x0 = floor(r.left()); // Floor gives the coordinate in which the point resides
- item->bbox.y0 = floor(r.top());
- item->bbox.x1 = ceil(r.right()); // Ceil gives the first coordinate beyond the point
- item->bbox.y1 = ceil(r.bottom());
- } else {
- item->bbox.x0 = (int) gc->transform[4];
- item->bbox.y0 = (int) gc->transform[5];
- item->bbox.x1 = item->bbox.x0 - 1;
- item->bbox.y1 = item->bbox.y0 - 1;
- }
-
- return NR_ARENA_ITEM_STATE_ALL;
-}
-
-static unsigned int nr_arena_image_render( cairo_t *ct, NRArenaItem *item, NRRectL * /*area*/, NRPixBlock * /*pb*/, unsigned int /*flags*/ )
-{
- if (!ct) {
- return item->state;
- }
-
- bool outline = (item->arena->rendermode == Inkscape::RENDERMODE_OUTLINE);
-
- NRArenaImage *image = NR_ARENA_IMAGE (item);
-
- if (!outline) {
- if (!image->pixbuf) {
- return item->state;
- }
-
- // FIXME: at the moment gdk_cairo_set_source_pixbuf creates an ARGB copy
- // of the pixbuf. Fix this in Cairo and/or GDK.
- cairo_save(ct);
- ink_cairo_transform(ct, image->ctm);
-
- cairo_new_path(ct);
- cairo_rectangle(ct, image->clipbox.left(), image->clipbox.top(),
- image->clipbox.width(), image->clipbox.height());
- cairo_clip(ct);
-
- cairo_translate(ct, image->ox, image->oy);
- cairo_scale(ct, image->sx, image->sy);
-
- cairo_set_source_surface(ct, image->surface, 0, 0);
-
- cairo_matrix_t tt;
- Geom::Affine total;
- cairo_get_matrix(ct, &tt);
- ink_matrix_to_2geom(total, tt);
-
- if (total.expansionX() > 1.0 || total.expansionY() > 1.0) {
- cairo_pattern_t *p = cairo_get_source(ct);
- cairo_pattern_set_filter(p, CAIRO_FILTER_NEAREST);
- }
-
- cairo_paint_with_alpha(ct, ((double) item->opacity) / 255.0);
- cairo_restore(ct);
-
- } else { // outline; draw a rect instead
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- guint32 rgba = prefs->getInt("/options/wireframecolors/images", 0xff0000ff);
-
- cairo_save(ct);
- ink_cairo_transform(ct, image->ctm);
-
- cairo_new_path(ct);
-
- Geom::Rect r = nr_arena_image_rect (image);
- Geom::Point c00 = r.corner(0);
- Geom::Point c01 = r.corner(3);
- Geom::Point c11 = r.corner(2);
- Geom::Point c10 = r.corner(1);
-
- cairo_move_to (ct, c00[Geom::X], c00[Geom::Y]);
- // the box
- cairo_line_to (ct, c10[Geom::X], c10[Geom::Y]);
- cairo_line_to (ct, c11[Geom::X], c11[Geom::Y]);
- cairo_line_to (ct, c01[Geom::X], c01[Geom::Y]);
- cairo_line_to (ct, c00[Geom::X], c00[Geom::Y]);
- // the diagonals
- cairo_line_to (ct, c11[Geom::X], c11[Geom::Y]);
- cairo_move_to (ct, c10[Geom::X], c10[Geom::Y]);
- cairo_line_to (ct, c01[Geom::X], c01[Geom::Y]);
- cairo_restore(ct);
-
- cairo_set_line_width(ct, 0.5);
- ink_cairo_set_source_rgba32(ct, rgba);
- cairo_stroke(ct);
- }
- return item->state;
-}
-
-/** Calculates the closest distance from p to the segment a1-a2*/
-double
-distance_to_segment (Geom::Point p, Geom::Point a1, Geom::Point a2)
-{
- // calculate sides of the triangle and their squares
- double d1 = Geom::L2(p - a1);
- double d1_2 = d1 * d1;
- double d2 = Geom::L2(p - a2);
- double d2_2 = d2 * d2;
- double a = Geom::L2(a1 - a2);
- double a_2 = a * a;
-
- // if one of the angles at the base is > 90, return the corresponding side
- if (d1_2 + a_2 <= d2_2) return d1;
- if (d2_2 + a_2 <= d1_2) return d2;
-
- // otherwise calculate the height to the base
- double peri = (a + d1 + d2)/2;
- return (2*sqrt(peri * (peri - a) * (peri - d1) * (peri - d2))/a);
-}
-
-static NRArenaItem *
-nr_arena_image_pick( NRArenaItem *item, Geom::Point p, double delta, unsigned int /*sticky*/ )
-{
- NRArenaImage *image = NR_ARENA_IMAGE (item);
-
- if (!image->pixbuf) return NULL;
-
- bool outline = (item->arena->rendermode == Inkscape::RENDERMODE_OUTLINE);
-
- if (outline) {
- Geom::Rect r = nr_arena_image_rect (image);
-
- Geom::Point c00 = r.corner(0);
- Geom::Point c01 = r.corner(3);
- Geom::Point c11 = r.corner(2);
- Geom::Point c10 = r.corner(1);
-
- // frame
- if (distance_to_segment (p, c00, c10) < delta) return item;
- if (distance_to_segment (p, c10, c11) < delta) return item;
- if (distance_to_segment (p, c11, c01) < delta) return item;
- if (distance_to_segment (p, c01, c00) < delta) return item;
-
- // diagonals
- if (distance_to_segment (p, c00, c11) < delta) return item;
- if (distance_to_segment (p, c10, c01) < delta) return item;
-
- return NULL;
-
- } else {
-
- unsigned char *const pixels = gdk_pixbuf_get_pixels(image->pixbuf);
- int const width = gdk_pixbuf_get_width(image->pixbuf);
- int const height = gdk_pixbuf_get_height(image->pixbuf);
- int const rowstride = gdk_pixbuf_get_rowstride(image->pixbuf);
-
- Geom::Point tp = p * image->ctm.inverse();
- Geom::Rect r = nr_arena_image_rect(image);
-
- if (!r.contains(tp))
- return NULL;
-
- double vw = width * image->sx;
- double vh = height * image->sy;
- int ix = floor((tp[Geom::X] - image->ox) / vw * width);
- int iy = floor((tp[Geom::Y] - image->oy) / vh * height);
-
- if ((ix < 0) || (iy < 0) || (ix >= width) || (iy >= height))
- return NULL;
-
- unsigned char *pix_ptr = pixels + iy * rowstride + ix * 4;
- // is the alpha not transparent?
- return (pix_ptr[3] > 0) ? item : NULL;
- }
-}
-
-Geom::Rect
-nr_arena_image_rect (NRArenaImage *image)
-{
- Geom::Rect r = image->clipbox;
-
- if (image->pixbuf) {
- double pw = gdk_pixbuf_get_width(image->pixbuf);
- double ph = gdk_pixbuf_get_height(image->pixbuf);
- double vw = pw * image->sx;
- double vh = ph * image->sy;
- Geom::Point p(image->ox, image->oy);
- Geom::Point wh(vw, vh);
- Geom::Rect view(p, p+wh);
- Geom::OptRect res = r & view;
- r = res ? *res : r;
- }
-
- return r;
-}
-
-/* Utility */
-
-void
-nr_arena_image_set_argb32_pixbuf (NRArenaImage *image, GdkPixbuf *pb)
-{
- nr_return_if_fail (image != NULL);
- nr_return_if_fail (NR_IS_ARENA_IMAGE (image));
-
- // when done in this order, it won't break if pb == image->pixbuf and the refcount is 1
- if (pb != NULL) {
- g_object_ref (pb);
- }
- if (image->pixbuf != NULL) {
- g_object_unref(image->pixbuf);
- cairo_surface_destroy(image->surface);
- }
- image->pixbuf = pb;
- image->surface = pb ? ink_cairo_surface_create_for_argb32_pixbuf(pb) : NULL;
-
- nr_arena_item_request_update (NR_ARENA_ITEM (image), NR_ARENA_ITEM_STATE_ALL, FALSE);
-}
-
-void
-nr_arena_image_set_clipbox (NRArenaImage *image, Geom::Rect const &clip)
-{
- nr_return_if_fail (image != NULL);
- nr_return_if_fail (NR_IS_ARENA_IMAGE (image));
-
- image->clipbox = clip;
-
- nr_arena_item_request_update (NR_ARENA_ITEM (image), NR_ARENA_ITEM_STATE_ALL, FALSE);
-}
-
-void
-nr_arena_image_set_origin (NRArenaImage *image, Geom::Point const &origin)
-{
- nr_return_if_fail (image != NULL);
- nr_return_if_fail (NR_IS_ARENA_IMAGE (image));
-
- image->ox = origin[Geom::X];
- image->oy = origin[Geom::Y];
-
- nr_arena_item_request_update (NR_ARENA_ITEM (image), NR_ARENA_ITEM_STATE_ALL, FALSE);
-}
-
-void
-nr_arena_image_set_scale (NRArenaImage *image, double sx, double sy)
-{
- nr_return_if_fail (image != NULL);
- nr_return_if_fail (NR_IS_ARENA_IMAGE (image));
-
- image->sx = sx;
- image->sy = sy;
-
- nr_arena_item_request_update (NR_ARENA_ITEM (image), NR_ARENA_ITEM_STATE_ALL, FALSE);
-}
-
-void nr_arena_image_set_style (NRArenaImage *image, SPStyle *style)
-{
- g_return_if_fail(image != NULL);
- g_return_if_fail(NR_IS_ARENA_IMAGE(image));
-
- if (style) sp_style_ref(style);
- if (image->style) sp_style_unref(image->style);
- image->style = style;
-
- //if image has a filter
- if (style->filter.set && style->getFilter()) {
- if (!image->filter) {
- int primitives = sp_filter_primitive_count(SP_FILTER(style->getFilter()));
- image->filter = new Inkscape::Filters::Filter(primitives);
- }
- sp_filter_build_renderer(SP_FILTER(style->getFilter()), image->filter);
- } else {
- //no filter set for this image
- delete image->filter;
- image->filter = NULL;
- }
-
- if (style && style->enable_background.set
- && style->enable_background.value == SP_CSS_BACKGROUND_NEW) {
- image->background_new = true;
- }
-
- nr_arena_item_request_update(image, NR_ARENA_ITEM_STATE_ALL, FALSE);
-}
-
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/nr-arena-image.h b/src/display/nr-arena-image.h
deleted file mode 100644
index 6fa9223dd..000000000
--- a/src/display/nr-arena-image.h
+++ /dev/null
@@ -1,66 +0,0 @@
-#ifndef __NR_ARENA_IMAGE_H__
-#define __NR_ARENA_IMAGE_H__
-
-/*
- * RGBA display list system for inkscape
- *
- * Author:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * Copyright (C) 2001-2002 Lauris Kaplinski
- * Copyright (C) 2001 Ximian, Inc.
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include <gdk-pixbuf/gdk-pixbuf.h>
-#include <2geom/rect.h>
-#include "nr-arena-item.h"
-#include "style.h"
-
-#define NR_TYPE_ARENA_IMAGE (nr_arena_image_get_type ())
-#define NR_ARENA_IMAGE(o) (NR_CHECK_INSTANCE_CAST ((o), NR_TYPE_ARENA_IMAGE, NRArenaImage))
-#define NR_IS_ARENA_IMAGE(o) (NR_CHECK_INSTANCE_TYPE ((o), NR_TYPE_ARENA_IMAGE))
-
-NRType nr_arena_image_get_type (void);
-
-struct NRArenaImage : public NRArenaItem {
- GdkPixbuf *pixbuf;
- cairo_surface_t *surface;
-
- Geom::Affine ctm;
- Geom::Rect clipbox;
- double ox, oy;
- double sx, sy;
-
- SPStyle *style;
-
- static NRArenaImage *create(NRArena *arena) {
- NRArenaImage *obj=reinterpret_cast<NRArenaImage *>(nr_object_new(NR_TYPE_ARENA_IMAGE));
- obj->init(arena);
- return obj;
- }
-};
-
-struct NRArenaImageClass {
- NRArenaItemClass parent_class;
-};
-
-void nr_arena_image_set_argb32_pixbuf (NRArenaImage *image, GdkPixbuf *pb);
-void nr_arena_image_set_style (NRArenaImage *image, SPStyle *style);
-void nr_arena_image_set_clipbox (NRArenaImage *image, Geom::Rect const &clip);
-void nr_arena_image_set_origin (NRArenaImage *image, Geom::Point const &origin);
-void nr_arena_image_set_scale (NRArenaImage *image, double sx, double sy);
-
-#endif
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/nr-arena-item.cpp b/src/display/nr-arena-item.cpp
deleted file mode 100644
index 9ca5a7463..000000000
--- a/src/display/nr-arena-item.cpp
+++ /dev/null
@@ -1,882 +0,0 @@
-#define __NR_ARENA_ITEM_C__
-
-/*
- * RGBA display list system for inkscape
- *
- * Author:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * Copyright (C) 2001-2002 Lauris Kaplinski
- * Copyright (C) 2001 Ximian, Inc.
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#define noNR_ARENA_ITEM_VERBOSE
-#define noNR_ARENA_ITEM_DEBUG_CASCADE
-
-#include <cstring>
-#include <string>
-#include <cairomm/cairomm.h>
-
-#include "display/cairo-utils.h"
-#include "display/cairo-templates.h"
-#include "display/canvas-arena.h"
-#include "nr-arena.h"
-#include "nr-arena-item.h"
-#include "gc-core.h"
-#include "helper/geom.h"
-
-#include "nr-filter.h"
-#include "nr-arena-group.h"
-#include "preferences.h"
-
-namespace GC = Inkscape::GC;
-
-static void nr_arena_item_class_init (NRArenaItemClass *klass);
-static void nr_arena_item_init (NRArenaItem *item);
-static void nr_arena_item_private_finalize (NRObject *object);
-
-static NRObjectClass *parent_class;
-
-NRType
-nr_arena_item_get_type (void)
-{
- static NRType type = 0;
- if (!type) {
- type = nr_object_register_type (NR_TYPE_OBJECT,
- "NRArenaItem",
- sizeof (NRArenaItemClass),
- sizeof (NRArenaItem),
- (void (*)(NRObjectClass *))
- nr_arena_item_class_init,
- (void (*)(NRObject *))
- nr_arena_item_init);
- }
- return type;
-}
-
-static void
-nr_arena_item_class_init (NRArenaItemClass *klass)
-{
- NRObjectClass *object_class;
-
- object_class = (NRObjectClass *) klass;
-
- parent_class = ((NRObjectClass *) klass)->parent;
-
- object_class->finalize = nr_arena_item_private_finalize;
- object_class->cpp_ctor = NRObject::invoke_ctor < NRArenaItem >;
-}
-
-static void
-nr_arena_item_init (NRArenaItem *item)
-{
- item->arena = NULL;
- item->parent = NULL;
- item->next = item->prev = NULL;
-
- item->key = 0;
-
- item->state = 0;
- item->sensitive = TRUE;
- item->visible = TRUE;
-
- memset (&item->bbox, 0, sizeof (item->bbox));
- memset (&item->drawbox, 0, sizeof (item->drawbox));
- item->transform = NULL;
- item->ctm.setIdentity();
- item->opacity = 255;
- item->render_opacity = FALSE;
-
- item->transform = NULL;
- item->clip = NULL;
- item->mask = NULL;
- item->px = NULL;
- item->data = NULL;
- item->filter = NULL;
- item->background_pb = NULL;
- item->background_new = false;
-}
-
-static void
-nr_arena_item_private_finalize (NRObject *object)
-{
- NRArenaItem *item = static_cast < NRArenaItem * >(object);
-
- item->px = NULL;
- item->transform = NULL;
-
- if (item->clip)
- nr_arena_item_detach(item, item->clip);
- if (item->mask)
- nr_arena_item_detach(item, item->mask);
-
- ((NRObjectClass *) (parent_class))->finalize (object);
-}
-
-NRArenaItem *
-nr_arena_item_children (NRArenaItem *item)
-{
- nr_return_val_if_fail (item != NULL, NULL);
- nr_return_val_if_fail (NR_IS_ARENA_ITEM (item), NULL);
-
- if (NR_ARENA_ITEM_VIRTUAL (item, children))
- return NR_ARENA_ITEM_VIRTUAL (item, children) (item);
-
- return NULL;
-}
-
-NRArenaItem *
-nr_arena_item_last_child (NRArenaItem *item)
-{
- nr_return_val_if_fail (item != NULL, NULL);
- nr_return_val_if_fail (NR_IS_ARENA_ITEM (item), NULL);
-
- if (NR_ARENA_ITEM_VIRTUAL (item, last_child)) {
- return NR_ARENA_ITEM_VIRTUAL (item, last_child) (item);
- } else {
- NRArenaItem *ref = nr_arena_item_children (item);
- if (ref)
- while (ref->next)
- ref = ref->next;
- return ref;
- }
-}
-
-void
-nr_arena_item_add_child (NRArenaItem *item, NRArenaItem *child,
- NRArenaItem *ref)
-{
- nr_return_if_fail (item != NULL);
- nr_return_if_fail (NR_IS_ARENA_ITEM (item));
- nr_return_if_fail (child != NULL);
- nr_return_if_fail (NR_IS_ARENA_ITEM (child));
- nr_return_if_fail (child->parent == NULL);
- nr_return_if_fail (child->prev == NULL);
- nr_return_if_fail (child->next == NULL);
- nr_return_if_fail (child->arena == item->arena);
- nr_return_if_fail (child != ref);
- nr_return_if_fail (!ref || NR_IS_ARENA_ITEM (ref));
- nr_return_if_fail (!ref || (ref->parent == item));
-
- if (NR_ARENA_ITEM_VIRTUAL (item, add_child))
- NR_ARENA_ITEM_VIRTUAL (item, add_child) (item, child, ref);
-}
-
-void
-nr_arena_item_remove_child (NRArenaItem *item, NRArenaItem *child)
-{
- nr_return_if_fail (item != NULL);
- nr_return_if_fail (NR_IS_ARENA_ITEM (item));
- nr_return_if_fail (child != NULL);
- nr_return_if_fail (NR_IS_ARENA_ITEM (child));
- nr_return_if_fail (child->parent == item);
-
- if (NR_ARENA_ITEM_VIRTUAL (item, remove_child))
- NR_ARENA_ITEM_VIRTUAL (item, remove_child) (item, child);
-}
-
-void
-nr_arena_item_set_child_position (NRArenaItem *item, NRArenaItem *child,
- NRArenaItem *ref)
-{
- nr_return_if_fail (item != NULL);
- nr_return_if_fail (NR_IS_ARENA_ITEM (item));
- nr_return_if_fail (child != NULL);
- nr_return_if_fail (NR_IS_ARENA_ITEM (child));
- nr_return_if_fail (child->parent == item);
- nr_return_if_fail (!ref || NR_IS_ARENA_ITEM (ref));
- nr_return_if_fail (!ref || (ref->parent == item));
-
- if (NR_ARENA_ITEM_VIRTUAL (item, set_child_position))
- NR_ARENA_ITEM_VIRTUAL (item, set_child_position) (item, child, ref);
-}
-
-NRArenaItem *
-nr_arena_item_ref (NRArenaItem *item)
-{
- nr_object_ref ((NRObject *) item);
-
- return item;
-}
-
-NRArenaItem *
-nr_arena_item_unref (NRArenaItem *item)
-{
- nr_object_unref ((NRObject *) item);
-
- return NULL;
-}
-
-unsigned int
-nr_arena_item_invoke_update (NRArenaItem *item, NRRectL *area, NRGC *gc,
- unsigned int state, unsigned int reset)
-{
- NRGC childgc (gc);
- bool filter = (item->arena->rendermode == Inkscape::RENDERMODE_NORMAL);
- bool outline = (item->arena->rendermode == Inkscape::RENDERMODE_OUTLINE);
-
- nr_return_val_if_fail (item != NULL, NR_ARENA_ITEM_STATE_INVALID);
- nr_return_val_if_fail (NR_IS_ARENA_ITEM (item),
- NR_ARENA_ITEM_STATE_INVALID);
- nr_return_val_if_fail (!(state & NR_ARENA_ITEM_STATE_INVALID),
- NR_ARENA_ITEM_STATE_INVALID);
-
-#ifdef NR_ARENA_ITEM_DEBUG_CASCADE
- printf ("Update %s:%p %x %x %x\n",
- nr_type_name_from_instance ((GTypeInstance *) item), item, state,
- item->state, reset);
-#endif
-
- /* return if in error */
- if (item->state & NR_ARENA_ITEM_STATE_INVALID)
- return item->state;
- /* Set reset flags according to propagation status */
- if (item->propagate) {
- reset |= ~item->state;
- item->propagate = FALSE;
- }
- /* Reset our state */
- item->state &= ~reset;
- /* Return if NOP */
- if (!(~item->state & state))
- return item->state;
- /* Test whether to return immediately */
- if (area && (item->state & NR_ARENA_ITEM_STATE_BBOX)) {
- if (!nr_rect_l_test_intersect_ptr(area, outline ? &item->bbox : &item->drawbox))
- return item->state;
- }
-
- /* Reset image cache, if not to be kept */
- if (!(item->state & NR_ARENA_ITEM_STATE_IMAGE) && (item->px)) {
- item->px = NULL;
- }
-
- /* Set up local gc */
- childgc = *gc;
- if (item->transform) {
- childgc.transform = (*item->transform) * childgc.transform;
- }
- /* Remember the transformation matrix */
- item->ctm = childgc.transform;
-
- /* Invoke the real method */
- // that will update bbox
- item->state = NR_ARENA_ITEM_VIRTUAL (item, update) (item, area, &childgc, state, reset);
- if (item->state & NR_ARENA_ITEM_STATE_INVALID)
- return item->state;
-
- /* Enlarge the drawbox to contain filter effects */
- if (item->filter && filter && item->item_bbox) {
- item->drawbox.x0 = item->item_bbox->min()[Geom::X];
- item->drawbox.y0 = item->item_bbox->min()[Geom::Y];
- item->drawbox.x1 = item->item_bbox->max()[Geom::X];
- item->drawbox.y1 = item->item_bbox->max()[Geom::Y];
- item->filter->compute_drawbox (item, item->drawbox);
- } else {
- memcpy(&item->drawbox, &item->bbox, sizeof(item->bbox));
- }
-
- /* Clipping */
- if (item->clip) {
- // FIXME: since here we only need bbox, consider passing
- // ((state & !(NR_ARENA_ITEM_STATE_RENDER)) | NR_ARENA_ITEM_STATE_BBOX)
- // instead of state, so it does not have to create rendering structures in nr_arena_shape_update
- unsigned int newstate = nr_arena_item_invoke_update (item->clip, area, &childgc, state, reset);
- if (newstate & NR_ARENA_ITEM_STATE_INVALID) {
- item->state |= NR_ARENA_ITEM_STATE_INVALID;
- return item->state;
- }
- if (outline) {
- nr_rect_l_union(&item->bbox, &item->bbox, &item->clip->bbox);
- } else {
- // for clipping, we need geometric bbox
- nr_rect_l_intersect (&item->drawbox, &item->drawbox, &item->clip->bbox);
- }
- }
- /* Masking */
- if (item->mask) {
- unsigned int newstate = nr_arena_item_invoke_update (item->mask, area, &childgc, state, reset);
- if (newstate & NR_ARENA_ITEM_STATE_INVALID) {
- item->state |= NR_ARENA_ITEM_STATE_INVALID;
- return item->state;
- }
- if (outline) {
- nr_rect_l_union(&item->bbox, &item->bbox, &item->mask->bbox);
- } else {
- // for masking, we need full drawbox of mask
- nr_rect_l_intersect (&item->drawbox, &item->drawbox, &item->mask->drawbox);
- }
- }
-
- // now that we know drawbox, dirty the corresponding rect on canvas:
- if (!NR_IS_ARENA_GROUP(item) || (item->filter && filter)) {
- // unless filtered, groups do not need to render by themselves, only their members
- nr_arena_item_request_render (item);
- }
-
- return item->state;
-}
-
-struct MaskLuminanceToAlpha {
- guint32 operator()(guint32 in) {
- EXTRACT_ARGB32(in, a, r, g, b)
- // the operation of unpremul -> luminance-to-alpha -> multiply by alpha
- // is equivalent to luminance-to-alpha on premultiplied color values
- // original computation in double: r*0.2125 + g*0.7154 + b*0.0721
- guint32 ao = r*109 + g*366 + b*37; // coeffs add up to 512
- return ((ao + 256) << 15) & 0xff000000; // equivalent to ((ao + 256) / 512) << 24
- }
-};
-
-unsigned int
-nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area,
- NRPixBlock *pb, unsigned int flags)
-{
- bool outline = (item->arena->rendermode == Inkscape::RENDERMODE_OUTLINE);
- bool filter = (item->arena->rendermode != Inkscape::RENDERMODE_OUTLINE &&
- item->arena->rendermode != Inkscape::RENDERMODE_NO_FILTERS);
-
- nr_return_val_if_fail (item != NULL, NR_ARENA_ITEM_STATE_INVALID);
- nr_return_val_if_fail (NR_IS_ARENA_ITEM (item),
- NR_ARENA_ITEM_STATE_INVALID);
- nr_return_val_if_fail (item->state & NR_ARENA_ITEM_STATE_BBOX,
- item->state);
- if (!ct) return item->state;
-
-#ifdef NR_ARENA_ITEM_VERBOSE
- g_message ("Invoke render %p on %p: %d %d - %d %d, %d %d - %d %d", item, pb,
- area->x0, area->y0,
- area->x1, area->y1,
- item->drawbox.x0, item->drawbox.y0,
- item->drawbox.x1, item->drawbox.y1);
-#endif
-
- /* If we are invisible, just return successfully */
- if (!item->visible)
- return item->state | NR_ARENA_ITEM_STATE_RENDER;
-
- if (outline) {
- // intersect with bbox rather than drawbox, as we want to render things outside
- // of the clipping path as well
- NRRectL carea;
- nr_rect_l_intersect (&carea, area, &item->bbox);
- if (nr_rect_l_test_empty(carea))
- return item->state | NR_ARENA_ITEM_STATE_RENDER;
-
- // No caching in outline mode for now; investigate if it really gives any advantage with cairo.
- // Also no attempts to clip anything; just render everything: item, clip, mask
- // First, render the object itself
- unsigned int state = NR_ARENA_ITEM_VIRTUAL (item, render) (ct, item, &carea, pb, flags);
- if (state & NR_ARENA_ITEM_STATE_INVALID) {
- /* Clean up and return error */
- item->state |= NR_ARENA_ITEM_STATE_INVALID;
- return item->state;
- }
-
- // render clip and mask, if any
- guint32 saved_rgba = item->arena->outlinecolor; // save current outline color
- // render clippath as an object, using a different color
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- if (item->clip) {
- item->arena->outlinecolor = prefs->getInt("/options/wireframecolors/clips", 0x00ff00ff); // green clips
- NR_ARENA_ITEM_VIRTUAL (item->clip, render) (ct, item->clip, &carea, pb, flags);
- }
- // render mask as an object, using a different color
- if (item->mask) {
- item->arena->outlinecolor = prefs->getInt("/options/wireframecolors/masks", 0x0000ffff); // blue masks
- NR_ARENA_ITEM_VIRTUAL (item->mask, render) (ct, item->mask, &carea, pb, flags);
- }
- item->arena->outlinecolor = saved_rgba; // restore outline color
-
- return item->state | NR_ARENA_ITEM_STATE_RENDER;
- }
-
- // carea is the bounding box for intermediate rendering.
- // NOTE: carea might be larger than area, because of filter effects.
- NRRectL carea;
- nr_rect_l_intersect (&carea, area, &item->drawbox);
- if (nr_rect_l_test_empty(carea))
- return item->state | NR_ARENA_ITEM_STATE_RENDER;
- if (item->filter && filter) {
- item->filter->area_enlarge (carea, item);
- nr_rect_l_intersect (&carea, &carea, &item->drawbox);
- }
-
- using namespace Inkscape;
-
- unsigned state;
- unsigned retstate;
-
- // determine whether this shape needs intermediate rendering.
- bool needs_intermediate_rendering = false;
- bool &nir = needs_intermediate_rendering;
- bool needs_opacity = (item->opacity != 255 && !item->render_opacity);
-
- // this item needs an intermediate rendering if:
- nir |= (item->clip != NULL); // 1. it has a clipping path
- nir |= (item->mask != NULL); // 2. it has a mask
- nir |= (item->filter != NULL && filter); // 3. it has a filter
- nir |= needs_opacity; // 4. it is non-opaque
-
- double opacity = static_cast<double>(item->opacity) / 255.0;
-
- /* How the rendering is done.
- *
- * Clipping, masking and opacity are done by rendering them to a surface
- * and then compositing the object's rendering onto it with the IN operator.
- * The object itself is rendered to a group.
- *
- * Opacity is done by rendering the clipping path with an alpha
- * value corresponding to the opacity. If there is no clipping path,
- * the entire intermediate surface is painted with alpha corresponding
- * to the opacity value.
- */
-
- // short-circuit the simple case.
- if (!needs_intermediate_rendering) {
- state = NR_ARENA_ITEM_VIRTUAL (item, render) (ct, item, &carea, pb, flags);
- if (state & NR_ARENA_ITEM_STATE_INVALID) {
- item->state |= NR_ARENA_ITEM_STATE_INVALID;
- return item->state;
- }
- return item->state | NR_ARENA_ITEM_STATE_RENDER;
- }
-
- cairo_surface_t *intermediate = cairo_surface_create_similar(
- cairo_get_group_target(ct), CAIRO_CONTENT_COLOR_ALPHA,
- carea.x1 - carea.x0, carea.y1 - carea.y0);
- cairo_t *ict = cairo_create(intermediate);
- cairo_translate(ict, -carea.x0, -carea.y0);
-
- // 1. Render clipping path with alpha = opacity.
- cairo_set_source_rgba(ict, 0,0,0,opacity);
- // Since clip can be combined with opacity, the result could be incorrect
- // for overlapping clip children. To fix this we use the SOURCE operator
- // instead of the default OVER.
- cairo_set_operator(ict, CAIRO_OPERATOR_SOURCE);
- if (item->clip) {
- state = nr_arena_item_invoke_clip(ict, item->clip, const_cast<NRRectL*>(area));
- if (state & NR_ARENA_ITEM_STATE_INVALID) {
- retstate = (item->state |= NR_ARENA_ITEM_STATE_INVALID);
- goto cleanup;
- }
- } else {
- // if there is no clipping path, fill the entire surface with alpha = opacity.
- cairo_paint(ict);
- }
- // reset back to default
- cairo_set_operator(ict, CAIRO_OPERATOR_OVER);
-
- // 2. Render the mask if present and compose it with the clipping path + opacity.
- if (item->mask) {
- cairo_push_group(ict);
- state = NR_ARENA_ITEM_VIRTUAL (item->mask, render) (ict, item->mask, &carea, NULL, flags);
- if (state & NR_ARENA_ITEM_STATE_INVALID) {
- retstate = (item->state |= NR_ARENA_ITEM_STATE_INVALID);
- goto cleanup;
- }
- cairo_surface_t *mask_s = cairo_get_group_target(ict);
- // Convert mask's luminance to alpha
- ink_cairo_surface_filter(mask_s, mask_s, MaskLuminanceToAlpha());
- cairo_pop_group_to_source(ict);
- cairo_set_operator(ict, CAIRO_OPERATOR_IN);
- cairo_paint(ict);
- cairo_set_operator(ict, CAIRO_OPERATOR_OVER);
- }
-
- // 3. Render object itself.
- cairo_push_group(ict);
- state = NR_ARENA_ITEM_VIRTUAL (item, render) (ict, item, &carea, pb, flags);
- if (state & NR_ARENA_ITEM_STATE_INVALID) {
- retstate = (item->state |= NR_ARENA_ITEM_STATE_INVALID);
- goto cleanup;
- }
-
- // 4. Apply filter.
- if (item->filter && filter) {
- // HACK: SPCanvasArena doesn't exist when this is called for offscreen rendering
- // Proper fix: call this function with a drawing context class
- // that contains information about the surface's bounds
- NRRectL bgarea;
- if (flags & NR_ARENA_ITEM_RENDER_NO_CACHE || !item->arena->canvasarena) {
- bgarea = carea;
- } else {
- bgarea = NRRectL(item->arena->canvasarena->cache_area);
- }
- item->filter->render(item, ct, &bgarea, ict, &carea);
- // Note that because the object was rendered to a group,
- // the internals of the filter need to use cairo_get_group_target()
- // instead of cairo_get_target().
- }
-
- // 5. Render object inside the composited mask + clip
- cairo_pop_group_to_source(ict);
- cairo_set_operator(ict, CAIRO_OPERATOR_IN);
- cairo_paint(ict);
-
- // 6. Paint the completed rendering onto the base context
- cairo_set_source_surface(ct, intermediate, carea.x0, carea.y0);
- cairo_paint(ct);
- cairo_set_source_rgba(ct, 0,0,0,0);
- // the call above is to clear a ref on the intermediate surface held by ct
-
- retstate = item->state | NR_ARENA_ITEM_STATE_RENDER;
-
- cleanup:
- cairo_destroy(ict);
- cairo_surface_destroy(intermediate);
-
- return retstate;
-}
-
-unsigned int
-nr_arena_item_invoke_clip (cairo_t *ct, NRArenaItem *item, NRRectL *area)
-{
- nr_return_val_if_fail (item != NULL, NR_ARENA_ITEM_STATE_INVALID);
- nr_return_val_if_fail (NR_IS_ARENA_ITEM (item),
- NR_ARENA_ITEM_STATE_INVALID);
-
-#ifdef NR_ARENA_ITEM_VERBOSE
- printf ("Invoke clip by %p: %d %d - %d %d, item bbox %d %d - %d %d\n",
- item, area->x0, area->y0, area->x1, area->y1, (&item->bbox)->x0,
- (&item->bbox)->y0, (&item->bbox)->x1, (&item->bbox)->y1);
-#endif
-
- unsigned retstate = 0;
-
- // don't bother if the object does not implement clipping (e.g. NRArenaImage)
- if (!((NRArenaItemClass *) NR_OBJECT_GET_CLASS (item))->clip)
- return retstate;
-
- if (item->visible && nr_rect_l_test_intersect_ptr(area, &item->bbox)) {
- // The item used as the clipping path itself has a clipping path.
- // Render this item's clipping path onto a temporary surface, then composite it with the item
- // using the IN operator
- if (item->clip) {
- cairo_push_group_with_content(ct, CAIRO_CONTENT_ALPHA);
- cairo_save(ct);
- cairo_set_source_rgba(ct, 0,0,0,1);
- nr_arena_item_invoke_clip(ct, item->clip, area);
- cairo_restore(ct);
- cairo_push_group_with_content(ct, CAIRO_CONTENT_ALPHA);
- }
-
- // rasterize the clipping path
- retstate = ((NRArenaItemClass *) NR_OBJECT_GET_CLASS (item))->
- clip (ct, item, area);
-
- if (item->clip) {
- cairo_pop_group_to_source(ct);
- cairo_set_operator(ct, CAIRO_OPERATOR_IN);
- cairo_paint(ct);
- cairo_pop_group_to_source(ct);
- cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE);
- cairo_paint(ct);
- }
- }
-
- return retstate;
-}
-
-NRArenaItem *
-nr_arena_item_invoke_pick (NRArenaItem *item, Geom::Point p, double delta,
- unsigned int sticky)
-{
- nr_return_val_if_fail (item != NULL, NULL);
- nr_return_val_if_fail (NR_IS_ARENA_ITEM (item), NULL);
-
- // Sometimes there's no BBOX in item->state, reason unknown (bug 992817); I made this not an assert to remove the warning
- if (!(item->state & NR_ARENA_ITEM_STATE_BBOX)
- || !(item->state & NR_ARENA_ITEM_STATE_PICK))
- return NULL;
-
- if (!sticky && !(item->visible && item->sensitive))
- return NULL;
-
- // TODO: rewrite using Geom::Rect
- const double x = p[Geom::X];
- const double y = p[Geom::Y];
-
- if (((x + delta) >= item->bbox.x0) &&
- ((x - delta) < item->bbox.x1) &&
- ((y + delta) >= item->bbox.y0) && ((y - delta) < item->bbox.y1))
- {
- if (((NRArenaItemClass *) NR_OBJECT_GET_CLASS (item))->pick)
- return ((NRArenaItemClass *) NR_OBJECT_GET_CLASS (item))->
- pick (item, p, delta, sticky);
- }
-
- return NULL;
-}
-
-void
-nr_arena_item_request_update (NRArenaItem *item, unsigned int reset,
- unsigned int propagate)
-{
- nr_return_if_fail (item != NULL);
- nr_return_if_fail (NR_IS_ARENA_ITEM (item));
- nr_return_if_fail (!(reset & NR_ARENA_ITEM_STATE_INVALID));
-
- if (propagate && !item->propagate)
- item->propagate = TRUE;
-
- if (item->state & reset) {
- item->state &= ~reset;
- if (item->parent) {
- nr_arena_item_request_update (item->parent, reset, FALSE);
- } else {
- nr_arena_request_update (item->arena, item);
- }
- }
-}
-
-void
-nr_arena_item_request_render (NRArenaItem *item)
-{
- nr_return_if_fail (item != NULL);
- nr_return_if_fail (NR_IS_ARENA_ITEM (item));
-
- bool outline = (item->arena->rendermode == Inkscape::RENDERMODE_OUTLINE);
- nr_arena_request_render_rect (item->arena, outline ? &item->bbox : &item->drawbox);
-}
-
-/* Public */
-
-NRArenaItem *
-nr_arena_item_unparent (NRArenaItem *item)
-{
- nr_return_val_if_fail (item != NULL, NULL);
- nr_return_val_if_fail (NR_IS_ARENA_ITEM (item), NULL);
-
- nr_arena_item_request_render (item);
-
- if (item->parent) {
- nr_arena_item_remove_child (item->parent, item);
- }
-
- return NULL;
-}
-
-void
-nr_arena_item_append_child (NRArenaItem *parent, NRArenaItem *child)
-{
- nr_return_if_fail (parent != NULL);
- nr_return_if_fail (NR_IS_ARENA_ITEM (parent));
- nr_return_if_fail (child != NULL);
- nr_return_if_fail (NR_IS_ARENA_ITEM (child));
- nr_return_if_fail (parent->arena == child->arena);
- nr_return_if_fail (child->parent == NULL);
- nr_return_if_fail (child->prev == NULL);
- nr_return_if_fail (child->next == NULL);
-
- nr_arena_item_add_child (parent, child, nr_arena_item_last_child (parent));
-}
-
-void
-nr_arena_item_set_transform (NRArenaItem *item, Geom::Affine const &transform)
-{
- Geom::Affine const t (transform);
- nr_arena_item_set_transform (item, &t);
-}
-
-void
-nr_arena_item_set_transform (NRArenaItem *item, Geom::Affine const *transform)
-{
- nr_return_if_fail (item != NULL);
- nr_return_if_fail (NR_IS_ARENA_ITEM (item));
-
- if (!transform && !item->transform)
- return;
-
- const Geom::Affine *md = (item->transform) ? item->transform : &GEOM_MATRIX_IDENTITY;
- const Geom::Affine *ms = (transform) ? transform : &GEOM_MATRIX_IDENTITY;
-
- if (!Geom::matrix_equalp(*md, *ms, NR_EPSILON)) {
- nr_arena_item_request_render (item);
- if (!transform || transform->isIdentity()) {
- /* Set to identity affine */
- item->transform = NULL;
- } else {
- if (!item->transform)
- item->transform = new (GC::ATOMIC) Geom::Affine ();
- *item->transform = *transform;
- }
- nr_arena_item_request_update (item, NR_ARENA_ITEM_STATE_ALL, TRUE);
- }
-}
-
-void
-nr_arena_item_set_opacity (NRArenaItem *item, double opacity)
-{
- nr_return_if_fail (item != NULL);
- nr_return_if_fail (NR_IS_ARENA_ITEM (item));
-
- nr_arena_item_request_render (item);
-
- item->opacity = (unsigned int) (opacity * 255.9999);
-}
-
-void
-nr_arena_item_set_sensitive (NRArenaItem *item, unsigned int sensitive)
-{
- nr_return_if_fail (item != NULL);
- nr_return_if_fail (NR_IS_ARENA_ITEM (item));
-
- /* fixme: mess with pick/repick... */
-
- item->sensitive = sensitive;
-}
-
-void
-nr_arena_item_set_visible (NRArenaItem *item, unsigned int visible)
-{
- nr_return_if_fail (item != NULL);
- nr_return_if_fail (NR_IS_ARENA_ITEM (item));
-
- item->visible = visible;
-
- nr_arena_item_request_render (item);
-}
-
-void
-nr_arena_item_set_clip (NRArenaItem *item, NRArenaItem *clip)
-{
- nr_return_if_fail (item != NULL);
- nr_return_if_fail (NR_IS_ARENA_ITEM (item));
- nr_return_if_fail (!clip || NR_IS_ARENA_ITEM (clip));
-
- if (clip != item->clip) {
- nr_arena_item_request_render (item);
- if (item->clip)
- item->clip = nr_arena_item_detach (item, item->clip);
- if (clip)
- item->clip = nr_arena_item_attach (item, clip, NULL, NULL);
- nr_arena_item_request_update (item, NR_ARENA_ITEM_STATE_ALL, TRUE);
- }
-}
-
-void
-nr_arena_item_set_mask (NRArenaItem *item, NRArenaItem *mask)
-{
- nr_return_if_fail (item != NULL);
- nr_return_if_fail (NR_IS_ARENA_ITEM (item));
- nr_return_if_fail (!mask || NR_IS_ARENA_ITEM (mask));
-
- if (mask != item->mask) {
- nr_arena_item_request_render (item);
- if (item->mask)
- item->mask = nr_arena_item_detach (item, item->mask);
- if (mask)
- item->mask = nr_arena_item_attach (item, mask, NULL, NULL);
- nr_arena_item_request_update (item, NR_ARENA_ITEM_STATE_ALL, TRUE);
- }
-}
-
-void
-nr_arena_item_set_order (NRArenaItem *item, int order)
-{
- nr_return_if_fail (item != NULL);
- nr_return_if_fail (NR_IS_ARENA_ITEM (item));
-
- if (!item->parent)
- return;
-
- NRArenaItem *children = nr_arena_item_children (item->parent);
-
- NRArenaItem *ref = NULL;
- int pos = 0;
- for (NRArenaItem *child = children; child != NULL; child = child->next) {
- if (pos >= order)
- break;
- if (child != item) {
- ref = child;
- pos += 1;
- }
- }
-
- nr_arena_item_set_child_position (item->parent, item, ref);
-}
-
-void
-nr_arena_item_set_item_bbox (NRArenaItem *item, Geom::OptRect &bbox)
-{
- nr_return_if_fail(item != NULL);
- nr_return_if_fail(NR_IS_ARENA_ITEM(item));
-
- item->item_bbox = bbox;
-}
-
-/** Returns a background image for use with filter effects. */
-NRPixBlock *nr_arena_item_get_background(NRArenaItem const * /*item*/)
-{
- return NULL;
-}
-
-/* Helpers */
-
-NRArenaItem *
-nr_arena_item_attach (NRArenaItem *parent, NRArenaItem *child,
- NRArenaItem *prev, NRArenaItem *next)
-{
- nr_return_val_if_fail (parent != NULL, NULL);
- nr_return_val_if_fail (NR_IS_ARENA_ITEM (parent), NULL);
- nr_return_val_if_fail (child != NULL, NULL);
- nr_return_val_if_fail (NR_IS_ARENA_ITEM (child), NULL);
- nr_return_val_if_fail (child->parent == NULL, NULL);
- nr_return_val_if_fail (child->prev == NULL, NULL);
- nr_return_val_if_fail (child->next == NULL, NULL);
- nr_return_val_if_fail (!prev || NR_IS_ARENA_ITEM (prev), NULL);
- nr_return_val_if_fail (!prev || (prev->parent == parent), NULL);
- nr_return_val_if_fail (!prev || (prev->next == next), NULL);
- nr_return_val_if_fail (!next || NR_IS_ARENA_ITEM (next), NULL);
- nr_return_val_if_fail (!next || (next->parent == parent), NULL);
- nr_return_val_if_fail (!next || (next->prev == prev), NULL);
-
- child->parent = parent;
- child->prev = prev;
- child->next = next;
-
- if (prev)
- prev->next = child;
- if (next)
- next->prev = child;
-
- return child;
-}
-
-NRArenaItem *
-nr_arena_item_detach (NRArenaItem *parent, NRArenaItem *child)
-{
- nr_return_val_if_fail (parent != NULL, NULL);
- nr_return_val_if_fail (NR_IS_ARENA_ITEM (parent), NULL);
- nr_return_val_if_fail (child != NULL, NULL);
- nr_return_val_if_fail (NR_IS_ARENA_ITEM (child), NULL);
- nr_return_val_if_fail (child->parent == parent, NULL);
-
- NRArenaItem *prev = child->prev;
- NRArenaItem *next = child->next;
-
- child->parent = NULL;
- child->prev = NULL;
- child->next = NULL;
-
- if (prev)
- prev->next = next;
- if (next)
- next->prev = prev;
-
- return next;
-}
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/nr-arena-item.h b/src/display/nr-arena-item.h
deleted file mode 100644
index d65a75ed8..000000000
--- a/src/display/nr-arena-item.h
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * RGBA display list system for inkscape
- *
- * Author:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * Copyright (C) 2001-2002 Lauris Kaplinski
- * Copyright (C) 2001 Ximian, Inc.
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#ifndef SEEN_DISPLAY_NR_ARENA_ITEM_H
-#define SEEN_DISPLAY_NR_ARENA_ITEM_H
-
-#include <cairo.h>
-#include <2geom/affine.h>
-#include <2geom/rect.h>
-#include "libnr/nr-forward.h"
-#include "libnr/nr-rect-l.h"
-#include "libnr/nr-object.h"
-#include "gc-soft-ptr.h"
-#include "nr-arena-forward.h"
-
-namespace Inkscape {
-namespace Filters {
-class Filter;
-} }
-
-#define NR_TYPE_ARENA_ITEM (nr_arena_item_get_type ())
-#define NR_ARENA_ITEM(o) (NR_CHECK_INSTANCE_CAST ((o), NR_TYPE_ARENA_ITEM, NRArenaItem))
-#define NR_IS_ARENA_ITEM(o) (NR_CHECK_INSTANCE_TYPE ((o), NR_TYPE_ARENA_ITEM))
-
-#define NR_ARENA_ITEM_VIRTUAL(i,m) (((NRArenaItemClass *) NR_OBJECT_GET_CLASS (i))->m)
-
-/*
- * NRArenaItem state flags
- */
-
-/*
- * NR_ARENA_ITEM_STATE_INVALID
- *
- * If set or retuned indicates, that given object is in error.
- * Calling method has to return immediately, with appropriate
- * error flag.
- */
-
-#define NR_ARENA_ITEM_STATE_INVALID (1 << 0)
-
-
-#define NR_ARENA_ITEM_STATE_BBOX (1 << 1)
-#define NR_ARENA_ITEM_STATE_COVERAGE (1 << 2)
-#define NR_ARENA_ITEM_STATE_DRAFT (1 << 3)
-#define NR_ARENA_ITEM_STATE_RENDER (1 << 4)
-#define NR_ARENA_ITEM_STATE_CLIP (1 << 5)
-#define NR_ARENA_ITEM_STATE_MASK (1 << 6)
-#define NR_ARENA_ITEM_STATE_PICK (1 << 7)
-#define NR_ARENA_ITEM_STATE_IMAGE (1 << 8)
-
-#define NR_ARENA_ITEM_STATE_NONE 0x0000
-#define NR_ARENA_ITEM_STATE_ALL 0x01fe
-
-#define NR_ARENA_ITEM_STATE(i,s) (NR_ARENA_ITEM (i)->state & (s))
-#define NR_ARENA_ITEM_SET_STATE(i,s) (NR_ARENA_ITEM (i)->state |= (s))
-#define NR_ARENA_ITEM_UNSET_STATE(i,s) (NR_ARENA_ITEM (i)->state &= ~(s))
-
-#define NR_ARENA_ITEM_RENDER_NO_CACHE (1 << 0)
-
-struct NRGC {
- NRGC(NRGC const *p) : parent(p) {}
- NRGC const *parent;
- Geom::Affine transform;
-};
-
-struct NRArenaItem : public NRObject {
-
- NRArena *arena;
- Inkscape::GC::soft_ptr<NRArenaItem> parent;
- NRArenaItem *next;
- Inkscape::GC::soft_ptr<NRArenaItem> prev;
-
- /* Item state */
- unsigned int state : 16;
- unsigned int propagate : 1;
- unsigned int sensitive : 1;
- unsigned int visible : 1;
- /* Whether items renders opacity itself */
- unsigned int render_opacity : 1;
- /* Opacity itself */
- unsigned int opacity : 8;
-
- unsigned int key; ///< Some SPItems can have more than one NRArenaItem,
- ///this value is a hack used to distinguish between them
-
- NRRectL bbox; ///< Bounding box in pixel grid coordinates; (0,0) is at page origin
- NRRectL drawbox; ///< Bounding box enlarged by filters, shrinked by clips and masks
- Geom::OptRect item_bbox; ///< Bounding box in item coordinates, required by filters
- Geom::Affine *transform; ///< Incremental transform of this item, as given by the transform= attribute
- Geom::Affine ctm; ///< Total transform from pixel grid to item coords
- NRArenaItem *clip; ///< Clipping path
- NRArenaItem *mask; ///< Mask
- Inkscape::Filters::Filter *filter; ///< Filter
- unsigned char *px; ///< Render cache; unused
-
- void *data; ///< Anonymous data member - this is used to associate SPItems with arena items
-
- NRPixBlock *background_pb; ///< Background for filters; unused
- bool background_new;
-
- void init(NRArena *arena) {
- this->arena = arena;
- }
-};
-
-struct NRArenaItemClass : public NRObjectClass {
- NRArenaItem * (* children) (NRArenaItem *item);
- NRArenaItem * (* last_child) (NRArenaItem *item);
- void (* add_child) (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref);
- void (* remove_child) (NRArenaItem *item, NRArenaItem *child);
- void (* set_child_position) (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref);
-
- unsigned int (* update) (NRArenaItem *item, NRRectL *area, NRGC *gc, unsigned int state, unsigned int reset);
- unsigned int (* render) (cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int flags);
- unsigned int (* clip) (cairo_t *ct, NRArenaItem *item, NRRectL *area);
- NRArenaItem * (* pick) (NRArenaItem *item, Geom::Point p, double delta, unsigned int sticky);
-};
-
-#define NR_ARENA_ITEM_ARENA(ai) (((NRArenaItem *) (ai))->arena)
-
-NRType nr_arena_item_get_type (void);
-
-NRArenaItem *nr_arena_item_ref (NRArenaItem *item);
-NRArenaItem *nr_arena_item_unref (NRArenaItem *item);
-
-NRArenaItem *nr_arena_item_children (NRArenaItem *item);
-NRArenaItem *nr_arena_item_last_child (NRArenaItem *item);
-void nr_arena_item_add_child (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref);
-void nr_arena_item_remove_child (NRArenaItem *item, NRArenaItem *child);
-void nr_arena_item_set_child_position (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref);
-
-/*
- * Invoke update to given state, if item is inside area
- *
- * area == NULL is infinite
- * gc is PARENT gc for invoke, CHILD gc in corresponding virtual method
- * state - requested to state (bitwise or of requested flags)
- * reset - reset to state (bitwise or of flags to reset)
- */
-
-unsigned int nr_arena_item_invoke_update (NRArenaItem *item, NRRectL *area, NRGC *gc, unsigned int state, unsigned int reset);
-
-unsigned int nr_arena_item_invoke_render(cairo_t *ct, NRArenaItem *item, NRRectL const *area, NRPixBlock *pb, unsigned int flags);
-
-unsigned int nr_arena_item_invoke_clip (cairo_t *ct, NRArenaItem *item, NRRectL *area);
-NRArenaItem *nr_arena_item_invoke_pick (NRArenaItem *item, Geom::Point p, double delta, unsigned int sticky);
-
-void nr_arena_item_request_update (NRArenaItem *item, unsigned int reset, unsigned int propagate);
-void nr_arena_item_request_render (NRArenaItem *item);
-
-/* Public */
-
-NRArenaItem *nr_arena_item_unparent (NRArenaItem *item);
-
-void nr_arena_item_append_child (NRArenaItem *parent, NRArenaItem *child);
-
-void nr_arena_item_set_transform(NRArenaItem *item, Geom::Affine const &transform);
-void nr_arena_item_set_transform(NRArenaItem *item, Geom::Affine const *transform);
-void nr_arena_item_set_opacity (NRArenaItem *item, double opacity);
-void nr_arena_item_set_sensitive (NRArenaItem *item, unsigned int sensitive);
-void nr_arena_item_set_visible (NRArenaItem *item, unsigned int visible);
-void nr_arena_item_set_clip (NRArenaItem *item, NRArenaItem *clip);
-void nr_arena_item_set_mask (NRArenaItem *item, NRArenaItem *mask);
-void nr_arena_item_set_order (NRArenaItem *item, int order);
-void nr_arena_item_set_item_bbox (NRArenaItem *item, Geom::OptRect &bbox);
-
-NRPixBlock *nr_arena_item_get_background (NRArenaItem const *item);
-
-/* Helpers */
-
-NRArenaItem *nr_arena_item_attach (NRArenaItem *parent, NRArenaItem *child, NRArenaItem *prev, NRArenaItem *next);
-NRArenaItem *nr_arena_item_detach (NRArenaItem *parent, NRArenaItem *child);
-
-#define NR_ARENA_ITEM_SET_DATA(i,v) (((NRArenaItem *) (i))->data = (v))
-#define NR_ARENA_ITEM_GET_DATA(i) (((NRArenaItem *) (i))->data)
-
-#define NR_ARENA_ITEM_SET_KEY(i,k) (((NRArenaItem *) (i))->key = (k))
-#define NR_ARENA_ITEM_GET_KEY(i) (((NRArenaItem *) (i))->key)
-
-#endif /* !SEEN_DISPLAY_NR_ARENA_ITEM_H */
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/nr-arena-shape.cpp b/src/display/nr-arena-shape.cpp
deleted file mode 100644
index 6d65611bf..000000000
--- a/src/display/nr-arena-shape.cpp
+++ /dev/null
@@ -1,610 +0,0 @@
-/*
- * RGBA display list system for inkscape
- *
- * Author:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * Copyright (C) 2001-2002 Lauris Kaplinski
- * Copyright (C) 2001 Ximian, Inc.
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include <cairo.h>
-#include <glib.h>
-#include <fenv.h>
-#include <typeinfo>
-
-#include <2geom/curves.h>
-#include <2geom/pathvector.h>
-#include <2geom/svg-path.h>
-#include <2geom/svg-path-parser.h>
-#include "display/cairo-utils.h"
-#include "display/canvas-arena.h"
-#include "display/canvas-bpath.h"
-#include "display/curve.h"
-#include "display/nr-arena.h"
-#include "display/nr-arena-shape.h"
-#include "display/nr-filter.h"
-#include "helper/geom-curves.h"
-#include "helper/geom.h"
-#include "libnr/nr-convert2geom.h"
-#include "preferences.h"
-#include "sp-filter.h"
-#include "sp-filter-reference.h"
-#include "style.h"
-#include "svg/svg.h"
-
-static void nr_arena_shape_class_init(NRArenaShapeClass *klass);
-static void nr_arena_shape_init(NRArenaShape *shape);
-static void nr_arena_shape_finalize(NRObject *object);
-
-static NRArenaItem *nr_arena_shape_children(NRArenaItem *item);
-static void nr_arena_shape_add_child(NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref);
-static void nr_arena_shape_remove_child(NRArenaItem *item, NRArenaItem *child);
-static void nr_arena_shape_set_child_position(NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref);
-
-static guint nr_arena_shape_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, guint reset);
-static unsigned int nr_arena_shape_render(cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int flags);
-static guint nr_arena_shape_clip(cairo_t *ct, NRArenaItem *item, NRRectL *area);
-static NRArenaItem *nr_arena_shape_pick(NRArenaItem *item, Geom::Point p, double delta, unsigned int sticky);
-
-static NRArenaItemClass *shape_parent_class;
-
-NRType
-nr_arena_shape_get_type(void)
-{
- static NRType type = 0;
- if (!type) {
- type = nr_object_register_type(NR_TYPE_ARENA_ITEM,
- "NRArenaShape",
- sizeof(NRArenaShapeClass),
- sizeof(NRArenaShape),
- (void (*)(NRObjectClass *)) nr_arena_shape_class_init,
- (void (*)(NRObject *)) nr_arena_shape_init);
- }
- return type;
-}
-
-static void
-nr_arena_shape_class_init(NRArenaShapeClass *klass)
-{
- NRObjectClass *object_class;
- NRArenaItemClass *item_class;
-
- object_class = (NRObjectClass *) klass;
- item_class = (NRArenaItemClass *) klass;
-
- shape_parent_class = (NRArenaItemClass *) ((NRObjectClass *) klass)->parent;
-
- object_class->finalize = nr_arena_shape_finalize;
- object_class->cpp_ctor = NRObject::invoke_ctor<NRArenaShape>;
-
- item_class->children = nr_arena_shape_children;
- item_class->add_child = nr_arena_shape_add_child;
- item_class->set_child_position = nr_arena_shape_set_child_position;
- item_class->remove_child = nr_arena_shape_remove_child;
- item_class->update = nr_arena_shape_update;
- item_class->render = nr_arena_shape_render;
- item_class->clip = nr_arena_shape_clip;
- item_class->pick = nr_arena_shape_pick;
-}
-
-/**
- * Initializes the arena shape, setting all parameters to null, 0, false,
- * or other defaults
- */
-static void
-nr_arena_shape_init(NRArenaShape *shape)
-{
- shape->curve = NULL;
- shape->style = NULL;
- shape->paintbox.x0 = shape->paintbox.y0 = 0.0F;
- shape->paintbox.x1 = shape->paintbox.y1 = 256.0F;
- shape->delayed_shp = false;
- shape->path = NULL;
-
- shape->approx_bbox.x0 = shape->approx_bbox.y0 = 0;
- shape->approx_bbox.x1 = shape->approx_bbox.y1 = 0;
-
- shape->markers = NULL;
- shape->last_pick = NULL;
- shape->repick_after = 0;
-}
-
-static void
-nr_arena_shape_finalize(NRObject *object)
-{
- NRArenaShape *shape = (NRArenaShape *) object;
-
- if (shape->path) cairo_path_destroy(shape->path);
- if (shape->style) sp_style_unref(shape->style);
- if (shape->curve) shape->curve->unref();
- shape->last_pick = NULL;
-
- ((NRObjectClass *) shape_parent_class)->finalize(object);
-}
-
-/**
- * Retrieves the markers from the item
- */
-static NRArenaItem *
-nr_arena_shape_children(NRArenaItem *item)
-{
- NRArenaShape *shape = (NRArenaShape *) item;
-
- return shape->markers;
-}
-
-/**
- * Attaches child to item, and if ref is not NULL, sets it and ref->next as
- * the prev and next items. If ref is NULL, then it sets the item's markers
- * as the next items.
- */
-static void
-nr_arena_shape_add_child(NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref)
-{
- NRArenaShape *shape = (NRArenaShape *) item;
-
- if (!ref) {
- shape->markers = nr_arena_item_attach(item, child, NULL, shape->markers);
- } else {
- ref->next = nr_arena_item_attach(item, child, ref, ref->next);
- }
-
- nr_arena_item_request_update(item, NR_ARENA_ITEM_STATE_ALL, FALSE);
-}
-
-/**
- * Removes child from the shape. If there are no prev items in
- * the child, it sets items' markers to the next item in the child.
- */
-static void
-nr_arena_shape_remove_child(NRArenaItem *item, NRArenaItem *child)
-{
- NRArenaShape *shape = (NRArenaShape *) item;
-
- if (child->prev) {
- nr_arena_item_detach(item, child);
- } else {
- shape->markers = nr_arena_item_detach(item, child);
- }
-
- nr_arena_item_request_update(item, NR_ARENA_ITEM_STATE_ALL, FALSE);
-}
-
-/**
- * Detaches child from item, and if there are no previous items in child, it
- * sets item's markers to the child. It then attaches the child back onto the item.
- * If ref is null, it sets the markers to be the next item, otherwise it uses
- * the next/prev items in ref.
- */
-static void
-nr_arena_shape_set_child_position(NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref)
-{
- NRArenaShape *shape = (NRArenaShape *) item;
-
- if (child->prev) {
- nr_arena_item_detach(item, child);
- } else {
- shape->markers = nr_arena_item_detach(item, child);
- }
-
- if (!ref) {
- shape->markers = nr_arena_item_attach(item, child, NULL, shape->markers);
- } else {
- ref->next = nr_arena_item_attach(item, child, ref, ref->next);
- }
-
- nr_arena_item_request_render(child);
-}
-
-/**
- * Updates the arena shape 'item' and all of its children, including the markers.
- */
-static guint
-nr_arena_shape_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, guint reset)
-{
- Geom::OptRect boundingbox;
-
- NRArenaShape *shape = NR_ARENA_SHAPE(item);
-
- unsigned int beststate = NR_ARENA_ITEM_STATE_ALL;
-
- // update markers
- unsigned int newstate;
- for (NRArenaItem *child = shape->markers; child != NULL; child = child->next) {
- newstate = nr_arena_item_invoke_update(child, area, gc, state, reset);
- beststate = beststate & newstate;
- }
-
- if (!(state & NR_ARENA_ITEM_STATE_RENDER)) {
- /* We do not have to create rendering structures */
- if (state & NR_ARENA_ITEM_STATE_BBOX) {
- if (shape->curve) {
- boundingbox = bounds_exact_transformed(shape->curve->get_pathvector(), gc->transform);
- if (boundingbox) {
- item->bbox.x0 = floor((*boundingbox)[0][0]); // Floor gives the coordinate in which the point resides
- item->bbox.y0 = floor((*boundingbox)[1][0]);
- item->bbox.x1 = ceil ((*boundingbox)[0][1]); // Ceil gives the first coordinate beyond the point
- item->bbox.y1 = ceil ((*boundingbox)[1][1]);
- } else {
- item->bbox = NR_RECT_L_EMPTY;
- }
- }
- if (beststate & NR_ARENA_ITEM_STATE_BBOX) {
- for (NRArenaItem *child = shape->markers; child != NULL; child = child->next) {
- nr_rect_l_union(&item->bbox, &item->bbox, &child->bbox);
- }
- }
- }
- return (state | item->state);
- }
-
- shape->delayed_shp=true;
- boundingbox = Geom::OptRect();
-
- bool outline = (NR_ARENA_ITEM(shape)->arena->rendermode == Inkscape::RENDERMODE_OUTLINE);
-
- // clear Cairo data to force update
- shape->nrstyle.update();
- if (shape->path) {
- cairo_path_destroy(shape->path);
- shape->path = NULL;
- }
-
- if (shape->curve) {
- boundingbox = bounds_exact_transformed(shape->curve->get_pathvector(), gc->transform);
-
- if (boundingbox && (shape->nrstyle.stroke.type != NRStyle::PAINT_NONE || outline)) {
- float width, scale;
- scale = gc->transform.descrim();
- width = MAX(0.125, shape->nrstyle.stroke_width * scale);
- if ( fabs(shape->nrstyle.stroke_width * scale) > 0.01 ) { // FIXME: this is always true
- boundingbox->expandBy(width);
- }
- // those pesky miters, now
- float miterMax = width * shape->nrstyle.miter_limit;
- if ( miterMax > 0.01 ) {
- // grunt mode. we should compute the various miters instead
- // (one for each point on the curve)
- boundingbox->expandBy(miterMax);
- }
- }
- }
-
- /// \todo just write item->bbox = boundingbox
- if (boundingbox) {
- shape->approx_bbox.x0 = floor(boundingbox->left());
- shape->approx_bbox.y0 = floor(boundingbox->top());
- shape->approx_bbox.x1 = ceil (boundingbox->right());
- shape->approx_bbox.y1 = ceil (boundingbox->bottom());
- } else {
- shape->approx_bbox = NR_RECT_L_EMPTY;
- }
- if ( area && nr_rect_l_test_intersect_ptr(area, &shape->approx_bbox) ) shape->delayed_shp=false;
-
- // TODO: compute a better bounding box that respects miters
- item->bbox = shape->approx_bbox;
-
- if (!shape->curve ||
- !shape->style ||
- shape->curve->is_empty() ||
- (( shape->nrstyle.fill.type != NRStyle::PAINT_NONE ) &&
- ( shape->nrstyle.stroke.type != NRStyle::PAINT_NONE && !outline) ))
- {
- //item->bbox = shape->approx_bbox;
- return NR_ARENA_ITEM_STATE_ALL;
- }
-
- if (beststate & NR_ARENA_ITEM_STATE_BBOX) {
- for (NRArenaItem *child = shape->markers; child != NULL; child = child->next) {
- nr_rect_l_union(&item->bbox, &item->bbox, &child->bbox);
- }
- }
-
- return NR_ARENA_ITEM_STATE_ALL;
-}
-
-// cairo outline rendering:
-static unsigned int
-cairo_arena_shape_render_outline(cairo_t *ct, NRArenaItem *item, Geom::OptRect /*area*/)
-{
- NRArenaShape *shape = NR_ARENA_SHAPE(item);
-
- if (!ct)
- return item->state;
-
- guint32 rgba = NR_ARENA_ITEM(shape)->arena->outlinecolor;
-
- cairo_save(ct);
- ink_cairo_transform(ct, shape->ctm);
- feed_pathvector_to_cairo (ct, shape->curve->get_pathvector());
- cairo_restore(ct);
- cairo_save(ct);
- ink_cairo_set_source_rgba32(ct, rgba);
- cairo_set_line_width(ct, 0.5);
- cairo_set_tolerance(ct, 1.25); // low quality, but good enough for outline mode
- cairo_stroke(ct);
- cairo_restore(ct);
-
- return item->state;
-}
-
-/**
- * Renders the item. Markers are just composed into the parent buffer.
- */
-static unsigned int
-nr_arena_shape_render(cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int flags)
-{
- NRArenaShape *shape = NR_ARENA_SHAPE(item);
-
- if (!shape->curve) return item->state;
- if (!shape->style) return item->state;
- if (!ct) return item->state;
-
- // skip if not within bounding box
- if (!nr_rect_l_test_intersect_ptr(area, &item->bbox)) {
- return item->state;
- }
-
- bool outline = (NR_ARENA_ITEM(shape)->arena->rendermode == Inkscape::RENDERMODE_OUTLINE);
-
- if (outline) { // cairo outline rendering
-
- NRRect temp(area->x0, area->y0, area->x1, area->y1);
- unsigned int ret = cairo_arena_shape_render_outline (ct, item, temp.upgrade_2geom());
- if (ret & NR_ARENA_ITEM_STATE_INVALID) return ret;
-
- } else {
- bool has_stroke, has_fill;
- // we assume the context has no path
- cairo_save(ct);
- ink_cairo_transform(ct, shape->ctm);
-
- // update fill and stroke paints.
- // this cannot be done during nr_arena_shape_update, because we need a Cairo context
- // to render svg:pattern
- has_fill = shape->nrstyle.prepareFill(ct, &shape->paintbox);
- has_stroke = shape->nrstyle.prepareStroke(ct, &shape->paintbox);
- has_stroke &= (shape->nrstyle.stroke_width != 0);
-
- if (has_fill || has_stroke) {
- // TODO: remove segments outside of bbox when no dashes present
- feed_pathvector_to_cairo(ct, shape->curve->get_pathvector());
- if (has_fill) {
- shape->nrstyle.applyFill(ct);
- cairo_fill_preserve(ct);
- }
- if (has_stroke) {
- shape->nrstyle.applyStroke(ct);
- cairo_stroke_preserve(ct);
- }
- cairo_new_path(ct); // clear path
- } // has fill or stroke pattern
- cairo_restore(ct);
- }
-
- // marker rendering
- for (NRArenaItem *child = shape->markers; child != NULL; child = child->next) {
- unsigned int ret = nr_arena_item_invoke_render(ct, child, area, pb, flags);
- if (ret & NR_ARENA_ITEM_STATE_INVALID) return ret;
- }
-
- return item->state;
-}
-
-
-static guint nr_arena_shape_clip(cairo_t *ct, NRArenaItem *item, NRRectL * /*area*/)
-{
- NRArenaShape *shape = NR_ARENA_SHAPE(item);
- if (!shape->curve) {
- return item->state;
- }
-
- cairo_save(ct);
- // handle clip-rule
- if (shape->style) {
- if (shape->style->clip_rule.computed == SP_WIND_RULE_EVENODD) {
- cairo_set_fill_rule(ct, CAIRO_FILL_RULE_EVEN_ODD);
- } else {
- cairo_set_fill_rule(ct, CAIRO_FILL_RULE_WINDING);
- }
- }
- ink_cairo_transform(ct, shape->ctm);
- feed_pathvector_to_cairo(ct, shape->curve->get_pathvector());
- cairo_fill(ct);
- cairo_restore(ct);
-
- return item->state;
-}
-
-static NRArenaItem *
-nr_arena_shape_pick(NRArenaItem *item, Geom::Point p, double delta, unsigned int /*sticky*/)
-{
- NRArenaShape *shape = NR_ARENA_SHAPE(item);
-
- if (shape->repick_after > 0)
- shape->repick_after--;
-
- if (shape->repick_after > 0) // we are a slow, huge path. skip this pick, returning what was returned last time
- return shape->last_pick;
-
- if (!shape->curve) return NULL;
- if (!shape->style) return NULL;
-
- bool outline = (NR_ARENA_ITEM(shape)->arena->rendermode == Inkscape::RENDERMODE_OUTLINE);
-
- if (SP_SCALE24_TO_FLOAT(shape->style->opacity.value) == 0 && !outline)
- // fully transparent, no pick unless outline mode
- return NULL;
-
- GTimeVal tstart, tfinish;
- g_get_current_time (&tstart);
-
- double width;
- if (outline) {
- width = 0.5;
- } else if (shape->nrstyle.stroke.type != NRStyle::PAINT_NONE && shape->nrstyle.stroke.opacity > 1e-3) {
- float const scale = shape->ctm.descrim();
- width = MAX(0.125, shape->nrstyle.stroke_width * scale) / 2;
- } else {
- width = 0;
- }
-
- double dist = Geom::infinity();
- int wind = 0;
- bool needfill = (shape->nrstyle.fill.type != NRStyle::PAINT_NONE
- && shape->nrstyle.fill.opacity > 1e-3 && !outline);
-
- if (item->arena->canvasarena) {
- Geom::Rect viewbox = item->arena->canvasarena->item.canvas->getViewbox();
- viewbox.expandBy (width);
- pathv_matrix_point_bbox_wind_distance(shape->curve->get_pathvector(), shape->ctm, p, NULL, needfill? &wind : NULL, &dist, 0.5, &viewbox);
- } else {
- pathv_matrix_point_bbox_wind_distance(shape->curve->get_pathvector(), shape->ctm, p, NULL, needfill? &wind : NULL, &dist, 0.5, NULL);
- }
-
- g_get_current_time (&tfinish);
- glong this_pick = (tfinish.tv_sec - tstart.tv_sec) * 1000000 + (tfinish.tv_usec - tstart.tv_usec);
- //g_print ("pick time %lu\n", this_pick);
-
- if (this_pick > 10000) { // slow picking, remember to skip several new picks
- shape->repick_after = this_pick / 5000;
- }
-
- // covered by fill?
- if (needfill) {
- if (!shape->style->fill_rule.computed) {
- if (wind != 0) {
- shape->last_pick = item;
- return item;
- }
- } else {
- if (wind & 0x1) {
- shape->last_pick = item;
- return item;
- }
- }
- }
-
- // close to the edge, as defined by strokewidth and delta?
- // this ignores dashing (as if the stroke is solid) and always works as if caps are round
- if (needfill || width > 0) { // if either fill or stroke visible,
- if ((dist - width) < delta) {
- shape->last_pick = item;
- return item;
- }
- }
-
- // if not picked on the shape itself, try its markers
- for (NRArenaItem *child = shape->markers; child != NULL; child = child->next) {
- NRArenaItem *ret = nr_arena_item_invoke_pick(child, p, delta, 0);
- if (ret) {
- shape->last_pick = item;
- return item;
- }
- }
-
- shape->last_pick = NULL;
- return NULL;
-}
-
-/**
- *
- * Requests a render of the shape, then if the shape is already a curve it
- * unrefs the old curve; if the new curve is valid it creates a copy of the
- * curve and adds it to the shape. Finally, it requests an update of the
- * arena for the shape.
- */
-void nr_arena_shape_set_path(NRArenaShape *shape, SPCurve *curve, bool /*justTrans*/)
-{
- g_return_if_fail(shape != NULL);
- g_return_if_fail(NR_IS_ARENA_SHAPE(shape));
-
- nr_arena_item_request_render(NR_ARENA_ITEM(shape));
-
- if (shape->curve) {
- shape->curve->unref();
- shape->curve = NULL;
- }
-
- if (curve) {
- shape->curve = curve;
- curve->ref();
- }
-
- nr_arena_item_request_update(NR_ARENA_ITEM(shape), NR_ARENA_ITEM_STATE_ALL, FALSE);
-}
-
-/** nr_arena_shape_set_style
- *
- * Unrefs any existing style and ref's to the given one, then requests an update of the arena
- */
-void
-nr_arena_shape_set_style(NRArenaShape *shape, SPStyle *style)
-{
- g_return_if_fail(shape != NULL);
- g_return_if_fail(NR_IS_ARENA_SHAPE(shape));
- g_return_if_fail(style != NULL);
-
- sp_style_ref(style);
- if (shape->style) sp_style_unref(shape->style);
- shape->style = style;
-
- shape->nrstyle.set(style);
-
- //if shape has a filter
- if (style->filter.set && style->getFilter()) {
- if (!shape->filter) {
- int primitives = sp_filter_primitive_count(SP_FILTER(style->getFilter()));
- shape->filter = new Inkscape::Filters::Filter(primitives);
- }
- sp_filter_build_renderer(SP_FILTER(style->getFilter()), shape->filter);
- } else {
- //no filter set for this shape
- delete shape->filter;
- shape->filter = NULL;
- }
-
- nr_arena_item_request_update(shape, NR_ARENA_ITEM_STATE_ALL, FALSE);
-}
-
-void
-nr_arena_shape_set_paintbox(NRArenaShape *shape, NRRect const *pbox)
-{
- g_return_if_fail(shape != NULL);
- g_return_if_fail(NR_IS_ARENA_SHAPE(shape));
- g_return_if_fail(pbox != NULL);
-
- if ((pbox->x0 < pbox->x1) && (pbox->y0 < pbox->y1)) {
- shape->paintbox = *pbox;
- } else {
- /* fixme: We kill warning, although not sure what to do here (Lauris) */
- shape->paintbox.x0 = shape->paintbox.y0 = 0.0F;
- shape->paintbox.x1 = shape->paintbox.y1 = 256.0F;
- }
-
- nr_arena_item_request_update(shape, NR_ARENA_ITEM_STATE_ALL, FALSE);
-}
-
-void NRArenaShape::setPaintBox(Geom::Rect const &pbox)
-{
- paintbox.x0 = pbox.min()[Geom::X];
- paintbox.y0 = pbox.min()[Geom::Y];
- paintbox.x1 = pbox.max()[Geom::X];
- paintbox.y1 = pbox.max()[Geom::Y];
-
- nr_arena_item_request_update(this, NR_ARENA_ITEM_STATE_ALL, FALSE);
-}
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/nr-arena-shape.h b/src/display/nr-arena-shape.h
deleted file mode 100644
index 7b86f7f59..000000000
--- a/src/display/nr-arena-shape.h
+++ /dev/null
@@ -1,81 +0,0 @@
-#ifndef __NR_ARENA_SHAPE_H__
-#define __NR_ARENA_SHAPE_H__
-
-/*
- * RGBA display list system for inkscape
- *
- * Author:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * Copyright (C) 2001-2002 Lauris Kaplinski
- * Copyright (C) 2001 Ximian, Inc.
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#define NR_TYPE_ARENA_SHAPE (nr_arena_shape_get_type ())
-#define NR_ARENA_SHAPE(obj) (NR_CHECK_INSTANCE_CAST ((obj), NR_TYPE_ARENA_SHAPE, NRArenaShape))
-#define NR_IS_ARENA_SHAPE(obj) (NR_CHECK_INSTANCE_TYPE ((obj), NR_TYPE_ARENA_SHAPE))
-
-#include <cairo.h>
-#include "display/display-forward.h"
-#include "forward.h"
-#include "nr-arena-item.h"
-#include "nr-style.h"
-#include "libnr/nr-rect.h"
-
-NRType nr_arena_shape_get_type (void);
-
-struct NRArenaShape : public NRArenaItem {
- /* Shape data */
- SPCurve *curve;
- SPStyle *style;
- NRStyle nrstyle;
- NRRect paintbox;
-
- cairo_path_t *path;
-
- // delayed_shp=true means the *_shp polygons are not computed yet
- // they'll be computed on demand in *_render(), *_pick() or *_clip()
- // the goal is to not uncross polygons that are outside the viewing region
- bool delayed_shp;
- // approximate bounding box, for the case when the polygons have been delayed
- NRRectL approx_bbox;
-
- /* Markers */
- NRArenaItem *markers;
-
- NRArenaItem *last_pick;
- guint repick_after;
-
- static NRArenaShape *create(NRArena *arena) {
- NRArenaShape *obj=reinterpret_cast<NRArenaShape *>(nr_object_new(NR_TYPE_ARENA_SHAPE));
- obj->init(arena);
- obj->key = 0;
- return obj;
- }
-
- void setPaintBox(Geom::Rect const &pbox);
-};
-
-struct NRArenaShapeClass {
- NRArenaItemClass parent_class;
-};
-
-void nr_arena_shape_set_path(NRArenaShape *shape, SPCurve *curve, bool justTrans);
-void nr_arena_shape_set_style(NRArenaShape *shape, SPStyle *style);
-void nr_arena_shape_set_paintbox(NRArenaShape *shape, NRRect const *pbox);
-
-
-#endif /* !__NR_ARENA_SHAPE_H__ */
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/nr-arena.cpp b/src/display/nr-arena.cpp
deleted file mode 100644
index ce62a81dc..000000000
--- a/src/display/nr-arena.cpp
+++ /dev/null
@@ -1,185 +0,0 @@
-#define __NR_ARENA_C__
-
-/*
- * RGBA display list system for inkscape
- *
- * Author:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * Copyright (C) 2001-2002 Lauris Kaplinski
- * Copyright (C) 2001 Ximian, Inc.
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include "nr-arena-item.h"
-#include "nr-arena.h"
-#include "nr-filter-gaussian.h"
-#include "nr-filter-types.h"
-#include "preferences.h"
-#include "color.h"
-#include "libnr/nr-rect.h"
-
-static void nr_arena_class_init (NRArenaClass *klass);
-static void nr_arena_init (NRArena *arena);
-static void nr_arena_finalize (NRObject *object);
-
-static NRActiveObjectClass *parent_class;
-
-NRType
-nr_arena_get_type (void)
-{
- static NRType type = 0;
- if (!type) {
- type = nr_object_register_type (NR_TYPE_ACTIVE_OBJECT,
- "NRArena",
- sizeof (NRArenaClass),
- sizeof (NRArena),
- (void (*) (NRObjectClass *)) nr_arena_class_init,
- (void (*) (NRObject *)) nr_arena_init);
- }
- return type;
-}
-
-static void
-nr_arena_class_init (NRArenaClass *klass)
-{
- NRObjectClass *object_class = (NRObjectClass *) klass;
-
- parent_class = (NRActiveObjectClass *) (((NRObjectClass *) klass)->parent);
-
- object_class->finalize = nr_arena_finalize;
- object_class->cpp_ctor = NRObject::invoke_ctor<NRArena>;
-}
-
-static void
-nr_arena_init (NRArena *arena)
-{
- arena->delta = 0; // to be set by desktop from prefs
- arena->renderoffscreen = false; // use render values from preferences otherwise render exact
- arena->rendermode = Inkscape::RENDERMODE_NORMAL; // default is normal render
- arena->colorrendermode = Inkscape::COLORRENDERMODE_NORMAL; // default is normal color
- arena->blurquality = BLUR_QUALITY_NORMAL;
- arena->filterquality = Inkscape::Filters::FILTER_QUALITY_NORMAL;
- arena->outlinecolor = 0xff; // black; to be set by desktop from bg color
- arena->canvasarena = NULL;
-}
-
-static void
-nr_arena_finalize (NRObject *object)
-{
- ((NRObjectClass *) (parent_class))->finalize (object);
-}
-
-void
-nr_arena_request_update (NRArena *arena, NRArenaItem *item)
-{
- NRActiveObject *aobject = (NRActiveObject *) arena;
-
- nr_return_if_fail (arena != NULL);
- nr_return_if_fail (NR_IS_ARENA (arena));
- nr_return_if_fail (item != NULL);
- nr_return_if_fail (NR_IS_ARENA_ITEM (item));
- // setup render parameter
- if (arena->renderoffscreen == false) {
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- arena->blurquality = prefs->getInt("/options/blurquality/value", 0);
- arena->filterquality = prefs->getInt("/options/filterquality/value", 0);
- } else {
- arena->blurquality = BLUR_QUALITY_BEST;
- arena->filterquality = Inkscape::Filters::FILTER_QUALITY_BEST;
- arena->rendermode = Inkscape::RENDERMODE_NORMAL;
- arena->colorrendermode = Inkscape::COLORRENDERMODE_NORMAL;
- }
-
- if (aobject->callbacks) {
- for (unsigned int i = 0; i < aobject->callbacks->length; i++) {
- NRObjectListener *listener = aobject->callbacks->listeners + i;
- NRArenaEventVector *avector = (NRArenaEventVector *) listener->vector;
- if ((listener->size >= sizeof (NRArenaEventVector)) && avector->request_update) {
- avector->request_update (arena, item, listener->data);
- }
- }
- }
-}
-
-void
-nr_arena_request_render_rect (NRArena *arena, NRRectL *area)
-{
- NRActiveObject *aobject = (NRActiveObject *) arena;
-
- nr_return_if_fail (arena != NULL);
- nr_return_if_fail (NR_IS_ARENA (arena));
- nr_return_if_fail (area != NULL);
-
- // setup render parameter
- if (arena->renderoffscreen == false) {
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- arena->blurquality = prefs->getInt("/options/blurquality/value", 0);
- arena->filterquality = prefs->getInt("/options/filterquality/value", 0);
- } else {
- arena->blurquality = BLUR_QUALITY_BEST;
- arena->filterquality = Inkscape::Filters::FILTER_QUALITY_BEST;
- arena->rendermode = Inkscape::RENDERMODE_NORMAL;
- arena->colorrendermode = Inkscape::COLORRENDERMODE_NORMAL;
- }
- if (aobject->callbacks && area && !nr_rect_l_test_empty_ptr(area)) {
- for (unsigned int i = 0; i < aobject->callbacks->length; i++) {
- NRObjectListener *listener = aobject->callbacks->listeners + i;
- NRArenaEventVector *avector = (NRArenaEventVector *) listener->vector;
- if ((listener->size >= sizeof (NRArenaEventVector)) && avector->request_render) {
- avector->request_render (arena, area, listener->data);
- }
- }
- }
-}
-
-/**
- set arena to offscreen mode
- rendering will be exact
- @param arena NRArena object
-*/
-void
-nr_arena_set_renderoffscreen (NRArena *arena)
-{
- nr_return_if_fail (arena != NULL);
- nr_return_if_fail (NR_IS_ARENA (arena));
-
- // the real assignment to the quality indicators is in the update function
- arena->renderoffscreen = true;
-
-}
-
-#define FLOAT_TO_UINT8(f) (int(f*255))
-#define RGBA_R(v) ((v) >> 24)
-#define RGBA_G(v) (((v) >> 16) & 0xff)
-#define RGBA_B(v) (((v) >> 8) & 0xff)
-#define RGBA_A(v) ((v) & 0xff)
-
-void nr_arena_separate_color_plates(guint32* rgba){
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- bool render_cyan = prefs->getBool("/options/printcolorspreview/cyan", true);
- bool render_magenta = prefs->getBool("/options/printcolorspreview/magenta", true);
- bool render_yellow = prefs->getBool("/options/printcolorspreview/yellow", true);
- bool render_black = prefs->getBool("/options/printcolorspreview/black", true);
-
- float rgb_v[3];
- float cmyk_v[4];
- sp_color_rgb_to_cmyk_floatv (cmyk_v, RGBA_R(*rgba)/256.0, RGBA_G(*rgba)/256.0, RGBA_B(*rgba)/256.0);
- sp_color_cmyk_to_rgb_floatv (rgb_v, render_cyan ? cmyk_v[0] : 0,
- render_magenta ? cmyk_v[1] : 0,
- render_yellow ? cmyk_v[2] : 0,
- render_black ? cmyk_v[3] : 0);
- *rgba = (FLOAT_TO_UINT8(rgb_v[0])<<24) + (FLOAT_TO_UINT8(rgb_v[1])<<16) + (FLOAT_TO_UINT8(rgb_v[2])<<8) + 0xff;
-}
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/nr-arena.h b/src/display/nr-arena.h
deleted file mode 100644
index 1c8216434..000000000
--- a/src/display/nr-arena.h
+++ /dev/null
@@ -1,69 +0,0 @@
-#ifndef __NR_ARENA_H__
-#define __NR_ARENA_H__
-
-/*
- * RGBA display list system for inkscape
- *
- * Author:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * Copyright (C) 2001-2002 Lauris Kaplinski
- * Copyright (C) 2001 Ximian, Inc.
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include <glib/gmacros.h>
-
-#include "display/rendermode.h"
-
-G_BEGIN_DECLS
-
-typedef struct _SPCanvasArena SPCanvasArena;
-
-G_END_DECLS
-
-#define NR_TYPE_ARENA (nr_arena_get_type ())
-#define NR_ARENA(o) (NR_CHECK_INSTANCE_CAST ((o), NR_TYPE_ARENA, NRArena))
-#define NR_IS_ARENA(o) (NR_CHECK_INSTANCE_TYPE ((o), NR_TYPE_ARENA))
-
-#include <libnr/nr-forward.h>
-#include <libnr/nr-object.h>
-#include "nr-arena-forward.h"
-
-class SPPainter;
-
-NRType nr_arena_get_type (void);
-
-struct NRArenaEventVector {
- NRObjectEventVector parent;
- void (* request_update) (NRArena *arena, NRArenaItem *item, void *data);
- void (* request_render) (NRArena *arena, NRRectL *area, void *data);
-};
-
-struct NRArena : public NRActiveObject {
- static NRArena *create() {
- return reinterpret_cast<NRArena *>(nr_object_new(NR_TYPE_ARENA));
- }
-
- double delta;
- bool renderoffscreen; // if true then rendering must be exact
- Inkscape::RenderMode rendermode;
- Inkscape::ColorRenderMode colorrendermode;
- int blurquality; // will be updated during update from preferences
- int filterquality; // will be updated during update from preferences
-
- guint32 outlinecolor;
- SPCanvasArena *canvasarena; // may be NULL is this arena is not the screen but used for export etc.
-};
-
-struct NRArenaClass : public NRActiveObjectClass {
-};
-
-void nr_arena_request_update (NRArena *arena, NRArenaItem *item);
-void nr_arena_request_render_rect (NRArena *arena, NRRectL *area);
-void nr_arena_set_renderoffscreen (NRArena *arena);
-
-void nr_arena_separate_color_plates(guint32* rgba);
-
-#endif
diff --git a/src/display/nr-filter-blend.cpp b/src/display/nr-filter-blend.cpp
index 3cec479fa..267883b4b 100644
--- a/src/display/nr-filter-blend.cpp
+++ b/src/display/nr-filter-blend.cpp
@@ -196,6 +196,22 @@ bool FilterBlend::can_handle_affine(Geom::Affine const &)
return true;
}
+double FilterBlend::complexity(Geom::Affine const &)
+{
+ return 1.1;
+}
+
+bool FilterBlend::uses_background()
+{
+ if (_input == NR_FILTER_BACKGROUNDIMAGE || _input == NR_FILTER_BACKGROUNDALPHA ||
+ _input2 == NR_FILTER_BACKGROUNDIMAGE || _input2 == NR_FILTER_BACKGROUNDALPHA)
+ {
+ return true;
+ } else {
+ return false;
+ }
+}
+
void FilterBlend::set_input(int slot) {
_input = slot;
}
diff --git a/src/display/nr-filter-blend.h b/src/display/nr-filter-blend.h
index 64b3c9284..957d3cfc8 100644
--- a/src/display/nr-filter-blend.h
+++ b/src/display/nr-filter-blend.h
@@ -39,6 +39,8 @@ public:
virtual void render_cairo(FilterSlot &slot);
virtual bool can_handle_affine(Geom::Affine const &);
+ virtual double complexity(Geom::Affine const &ctm);
+ virtual bool uses_background();
virtual void set_input(int slot);
virtual void set_input(int input, int slot);
diff --git a/src/display/nr-filter-colormatrix.cpp b/src/display/nr-filter-colormatrix.cpp
index 7eb2fa2e9..6fa34bf0b 100644
--- a/src/display/nr-filter-colormatrix.cpp
+++ b/src/display/nr-filter-colormatrix.cpp
@@ -192,6 +192,11 @@ void FilterColorMatrix::area_enlarge(NRRectL &/*area*/, Geom::Affine const &/*tr
{
}
+double FilterColorMatrix::complexity(Geom::Affine const &)
+{
+ return 2.0;
+}
+
void FilterColorMatrix::set_type(FilterColorMatrixType t){
type = t;
}
diff --git a/src/display/nr-filter-colormatrix.h b/src/display/nr-filter-colormatrix.h
index df851e0aa..5864a010e 100644
--- a/src/display/nr-filter-colormatrix.h
+++ b/src/display/nr-filter-colormatrix.h
@@ -38,6 +38,7 @@ public:
virtual void render_cairo(FilterSlot &slot);
virtual bool can_handle_affine(Geom::Affine const &);
virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans);
+ virtual double complexity(Geom::Affine const &ctm);
virtual void set_type(FilterColorMatrixType type);
virtual void set_value(gdouble value);
diff --git a/src/display/nr-filter-component-transfer.cpp b/src/display/nr-filter-component-transfer.cpp
index 80bc07df8..887352f62 100644
--- a/src/display/nr-filter-component-transfer.cpp
+++ b/src/display/nr-filter-component-transfer.cpp
@@ -308,6 +308,11 @@ void FilterComponentTransfer::area_enlarge(NRRectL &/*area*/, Geom::Affine const
{
}
+double FilterComponentTransfer::complexity(Geom::Affine const &)
+{
+ return 2.0;
+}
+
} /* namespace Filters */
} /* namespace Inkscape */
diff --git a/src/display/nr-filter-component-transfer.h b/src/display/nr-filter-component-transfer.h
index 89bc61403..6d65ae6d1 100644
--- a/src/display/nr-filter-component-transfer.h
+++ b/src/display/nr-filter-component-transfer.h
@@ -38,6 +38,7 @@ public:
virtual void render_cairo(FilterSlot &slot);
virtual bool can_handle_affine(Geom::Affine const &);
virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans);
+ virtual double complexity(Geom::Affine const &ctm);
FilterComponentTransferType type[4];
std::vector<gdouble> tableValues[4];
diff --git a/src/display/nr-filter-composite.cpp b/src/display/nr-filter-composite.cpp
index 694ccaec5..b25ecdf2c 100644
--- a/src/display/nr-filter-composite.cpp
+++ b/src/display/nr-filter-composite.cpp
@@ -139,6 +139,11 @@ void FilterComposite::set_arithmetic(double k1, double k2, double k3, double k4)
this->k4 = k4;
}
+double FilterComposite::complexity(Geom::Affine const &)
+{
+ return 1.1;
+}
+
} /* namespace Filters */
} /* namespace Inkscape */
diff --git a/src/display/nr-filter-composite.h b/src/display/nr-filter-composite.h
index 930898830..95579cc0e 100644
--- a/src/display/nr-filter-composite.h
+++ b/src/display/nr-filter-composite.h
@@ -28,6 +28,7 @@ public:
virtual void render_cairo(FilterSlot &);
virtual bool can_handle_affine(Geom::Affine const &);
+ virtual double complexity(Geom::Affine const &ctm);
virtual void set_input(int input);
virtual void set_input(int input, int slot);
diff --git a/src/display/nr-filter-convolve-matrix.cpp b/src/display/nr-filter-convolve-matrix.cpp
index 06e28b074..469baf346 100644
--- a/src/display/nr-filter-convolve-matrix.cpp
+++ b/src/display/nr-filter-convolve-matrix.cpp
@@ -212,6 +212,11 @@ void FilterConvolveMatrix::area_enlarge(NRRectL &area, Geom::Affine const &/*tra
area.y1 += orderY - targetY - 1;
}
+double FilterConvolveMatrix::complexity(Geom::Affine const &)
+{
+ return kernelMatrix.size();
+}
+
} /* namespace Filters */
} /* namespace Inkscape */
diff --git a/src/display/nr-filter-convolve-matrix.h b/src/display/nr-filter-convolve-matrix.h
index d13738260..8b7fc35d1 100644
--- a/src/display/nr-filter-convolve-matrix.h
+++ b/src/display/nr-filter-convolve-matrix.h
@@ -36,6 +36,7 @@ public:
virtual void render_cairo(FilterSlot &slot);
virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans);
+ virtual double complexity(Geom::Affine const &ctm);
void set_targetY(int coord);
void set_targetX(int coord);
diff --git a/src/display/nr-filter-diffuselighting.cpp b/src/display/nr-filter-diffuselighting.cpp
index eaed2a8bd..14144ace5 100644
--- a/src/display/nr-filter-diffuselighting.cpp
+++ b/src/display/nr-filter-diffuselighting.cpp
@@ -16,7 +16,6 @@
#include "display/cairo-templates.h"
#include "display/cairo-utils.h"
#include "display/nr-3dutils.h"
-#include "display/nr-arena-item.h"
#include "display/nr-filter-diffuselighting.h"
#include "display/nr-filter-slot.h"
#include "display/nr-filter-units.h"
@@ -172,6 +171,11 @@ void FilterDiffuseLighting::area_enlarge(NRRectL &area, Geom::Affine const & /*t
area.y1 += 1;
}
+double FilterDiffuseLighting::complexity(Geom::Affine const &)
+{
+ return 9.0;
+}
+
} /* namespace Filters */
} /* namespace Inkscape */
diff --git a/src/display/nr-filter-diffuselighting.h b/src/display/nr-filter-diffuselighting.h
index 6e39242f6..bb3ceccb3 100644
--- a/src/display/nr-filter-diffuselighting.h
+++ b/src/display/nr-filter-diffuselighting.h
@@ -33,6 +33,7 @@ public:
virtual ~FilterDiffuseLighting();
virtual void render_cairo(FilterSlot &slot);
virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans);
+ virtual double complexity(Geom::Affine const &ctm);
union {
SPFeDistantLight *distant;
diff --git a/src/display/nr-filter-displacement-map.cpp b/src/display/nr-filter-displacement-map.cpp
index 15200223b..75e310339 100644
--- a/src/display/nr-filter-displacement-map.cpp
+++ b/src/display/nr-filter-displacement-map.cpp
@@ -140,6 +140,11 @@ void FilterDisplacementMap::area_enlarge(NRRectL &area, Geom::Affine const &tran
area.y1 += (int)(scaley)+2;
}
+double FilterDisplacementMap::complexity(Geom::Affine const &)
+{
+ return 3.0;
+}
+
} /* namespace Filters */
} /* namespace Inkscape */
diff --git a/src/display/nr-filter-displacement-map.h b/src/display/nr-filter-displacement-map.h
index aec4b7eb6..393a904c1 100644
--- a/src/display/nr-filter-displacement-map.h
+++ b/src/display/nr-filter-displacement-map.h
@@ -27,12 +27,14 @@ public:
static FilterPrimitive *create();
virtual ~FilterDisplacementMap();
+ virtual void render_cairo(FilterSlot &slot);
+ virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans);
+ virtual double complexity(Geom::Affine const &ctm);
+
virtual void set_input(int slot);
virtual void set_input(int input, int slot);
virtual void set_scale(double s);
virtual void set_channel_selector(int s, FilterDisplacementMapChannelSelector channel);
- virtual void render_cairo(FilterSlot &slot);
- virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans);
private:
double scale;
diff --git a/src/display/nr-filter-flood.cpp b/src/display/nr-filter-flood.cpp
index a015d3f1f..5716c1bc5 100644
--- a/src/display/nr-filter-flood.cpp
+++ b/src/display/nr-filter-flood.cpp
@@ -86,6 +86,13 @@ void FilterFlood::area_enlarge(NRRectL &/*area*/, Geom::Affine const &/*trans*/)
{
}
+double FilterFlood::complexity(Geom::Affine const &)
+{
+ // flood is actually less expensive than normal rendering,
+ // but when flood is processed, the object has already been rendered
+ return 1.0;
+}
+
} /* namespace Filters */
} /* namespace Inkscape */
diff --git a/src/display/nr-filter-flood.h b/src/display/nr-filter-flood.h
index 6db90d439..f744e9f48 100644
--- a/src/display/nr-filter-flood.h
+++ b/src/display/nr-filter-flood.h
@@ -27,10 +27,14 @@ public:
virtual void render_cairo(FilterSlot &slot);
virtual bool can_handle_affine(Geom::Affine const &);
+ virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans);
+ virtual double complexity(Geom::Affine const &ctm);
+ virtual bool uses_background() { return false; }
+
virtual void set_opacity(double o);
virtual void set_color(guint32 c);
virtual void set_icc(SVGICCColor *icc_color);
- virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans);
+
private:
double opacity;
guint32 color;
diff --git a/src/display/nr-filter-gaussian.cpp b/src/display/nr-filter-gaussian.cpp
index d240c1a43..8a7244e02 100644
--- a/src/display/nr-filter-gaussian.cpp
+++ b/src/display/nr-filter-gaussian.cpp
@@ -509,7 +509,7 @@ gaussian_pass_IIR(Geom::Dim2 d, double deviation, cairo_surface_t *src, cairo_su
w, h, b, M, tmpdata, num_threads);
break;
default:
- assert(false);
+ g_warning("gaussian_pass_IIR: unsupported image format");
};
}
@@ -542,7 +542,7 @@ gaussian_pass_FIR(Geom::Dim2 d, double deviation, cairo_surface_t *src, cairo_su
w, h, &kernel[0], scr_len, num_threads);
break;
default:
- assert(false);
+ g_warning("gaussian_pass_FIR: unsupported image format");
};
}
@@ -641,6 +641,13 @@ void FilterGaussian::render_cairo(FilterSlot &slot)
}
}
+ // free the temporary data
+ if ( use_IIR_x || use_IIR_y ) {
+ for(int i = 0; i < threads; ++i) {
+ delete[] tmpdata[i];
+ }
+ }
+
cairo_surface_mark_dirty(downsampled);
if (resampling) {
cairo_surface_t *upsampled = cairo_surface_create_similar(downsampled, cairo_surface_get_content(downsampled),
@@ -682,6 +689,13 @@ bool FilterGaussian::can_handle_affine(Geom::Affine const &)
return false;
}
+double FilterGaussian::complexity(Geom::Affine const &trans)
+{
+ int area_x = _effect_area_scr(_deviation_x * trans.expansionX());
+ int area_y = _effect_area_scr(_deviation_y * trans.expansionY());
+ return 2.0 * area_x * area_y;
+}
+
void FilterGaussian::set_deviation(double deviation)
{
if(IS_FINITE(deviation) && deviation >= 0) {
diff --git a/src/display/nr-filter-gaussian.h b/src/display/nr-filter-gaussian.h
index 811502016..f52bea01e 100644
--- a/src/display/nr-filter-gaussian.h
+++ b/src/display/nr-filter-gaussian.h
@@ -37,6 +37,7 @@ public:
virtual void render_cairo(FilterSlot &slot);
virtual void area_enlarge(NRRectL &area, Geom::Affine const &m);
virtual bool can_handle_affine(Geom::Affine const &m);
+ virtual double complexity(Geom::Affine const &ctm);
/**
* Set the standard deviation value for gaussian blur. Deviation along
diff --git a/src/display/nr-filter-image.cpp b/src/display/nr-filter-image.cpp
index 0cb7901b3..a22d23548 100644
--- a/src/display/nr-filter-image.cpp
+++ b/src/display/nr-filter-image.cpp
@@ -13,8 +13,9 @@
#include "document.h"
#include "sp-item.h"
#include "display/cairo-utils.h"
-#include "display/nr-arena.h"
-#include "display/nr-arena-item.h"
+#include "display/drawing-context.h"
+#include "display/drawing.h"
+#include "display/drawing-item.h"
#include "display/nr-filter.h"
#include "display/nr-filter-image.h"
#include "display/nr-filter-units.h"
@@ -69,21 +70,20 @@ void FilterImage::render_cairo(FilterSlot &slot)
// TODO: do not recreate the rendering tree every time
// TODO: the entire thing is a hack, we should give filter primitives an "update" method
- // like the one for NRArenaItems
+ // like the one for DrawingItems
document->ensureUpToDate();
- NRArena* arena = NRArena::create();
+ Drawing drawing;
Geom::OptRect optarea = SVGElem->getBounds(Geom::identity());
if (!optarea) return;
unsigned const key = SPItem::display_key_new(1);
- NRArenaItem* ai = SVGElem->invoke_show(arena, key, SP_ITEM_SHOW_DISPLAY);
-
+ DrawingItem *ai = SVGElem->invoke_show(drawing, key, SP_ITEM_SHOW_DISPLAY);
if (!ai) {
- g_warning("feImage renderer: error creating NRArenaItem for SVG Element");
- nr_object_unref((NRObject *) arena);
+ g_warning("feImage renderer: error creating DrawingItem for SVG Element");
return;
}
+ drawing.setRoot(ai);
Geom::Rect area = *optarea;
Geom::Affine pu2pb = slot.get_units().get_matrix_primitiveunits2pb();
@@ -94,30 +94,18 @@ void FilterImage::render_cairo(FilterSlot &slot)
Geom::Rect sa = slot.get_slot_area();
cairo_surface_t *out = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
sa.width(), sa.height());
- cairo_t *ct = cairo_create(out);
- cairo_translate(ct, -sa.min()[Geom::X], -sa.min()[Geom::Y]);
- ink_cairo_transform(ct, pu2pb); // we are now in primitive units
- cairo_translate(ct, feImageX, feImageY);
- cairo_scale(ct, scaleX, scaleY);
-
- NRRectL render_rect;
- render_rect.x0 = floor(area.left());
- render_rect.y0 = floor(area.top());
- render_rect.x1 = ceil(area.right());
- render_rect.y1 = ceil(area.bottom());
- cairo_translate(ct, render_rect.x0, render_rect.y0);
+ Inkscape::DrawingContext ct(out, sa.min());
+ ct.transform(pu2pb); // we are now in primitive units
+ ct.translate(feImageX, feImageY);
+ ct.scale(scaleX, scaleY);
+
+ Geom::IntRect render_rect = area.roundOutwards();
+ ct.translate(render_rect.min());
// Update to renderable state
- NRGC gc(NULL);
- Geom::Affine t = Geom::identity();
- nr_arena_item_set_transform(ai, &t);
- gc.transform.setIdentity();
- nr_arena_item_invoke_update(ai, NULL, &gc,
- NR_ARENA_ITEM_STATE_ALL,
- NR_ARENA_ITEM_STATE_NONE);
- nr_arena_item_invoke_render(ct, ai, &render_rect, NULL, NR_ARENA_ITEM_RENDER_NO_CACHE);
+ drawing.update(render_rect);
+ drawing.render(ct, render_rect);
SVGElem->invoke_hide(key);
- nr_object_unref((NRObject*) arena);
slot.set(_output, out);
cairo_surface_destroy(out);
@@ -208,6 +196,12 @@ bool FilterImage::can_handle_affine(Geom::Affine const &)
return true;
}
+double FilterImage::complexity(Geom::Affine const &)
+{
+ // TODO: right now we cannot actually measure this in any meaningful way.
+ return 1.1;
+}
+
void FilterImage::set_href(const gchar *href){
if (feImageHref) g_free (feImageHref);
feImageHref = (href) ? g_strdup (href) : NULL;
diff --git a/src/display/nr-filter-image.h b/src/display/nr-filter-image.h
index 0651109ec..5af0b3338 100644
--- a/src/display/nr-filter-image.h
+++ b/src/display/nr-filter-image.h
@@ -29,6 +29,8 @@ public:
virtual void render_cairo(FilterSlot &slot);
virtual bool can_handle_affine(Geom::Affine const &);
+ virtual double complexity(Geom::Affine const &ctm);
+
void set_document( SPDocument *document );
void set_href(const gchar *href);
void set_region(SVGLength x, SVGLength y, SVGLength width, SVGLength height);
diff --git a/src/display/nr-filter-merge.cpp b/src/display/nr-filter-merge.cpp
index 51d3975cb..28ac19a19 100644
--- a/src/display/nr-filter-merge.cpp
+++ b/src/display/nr-filter-merge.cpp
@@ -67,6 +67,22 @@ bool FilterMerge::can_handle_affine(Geom::Affine const &)
return true;
}
+double FilterMerge::complexity(Geom::Affine const &)
+{
+ return 1.02;
+}
+
+bool FilterMerge::uses_background()
+{
+ for (int i = 0; i < _input_image.size(); ++i) {
+ int input = _input_image[i];
+ if (input == NR_FILTER_BACKGROUNDIMAGE || input == NR_FILTER_BACKGROUNDALPHA) {
+ return true;
+ }
+ }
+ return false;
+}
+
void FilterMerge::set_input(int slot) {
_input_image[0] = slot;
}
diff --git a/src/display/nr-filter-merge.h b/src/display/nr-filter-merge.h
index 263fc8026..238f9a3e7 100644
--- a/src/display/nr-filter-merge.h
+++ b/src/display/nr-filter-merge.h
@@ -26,6 +26,8 @@ public:
virtual void render_cairo(FilterSlot &);
virtual bool can_handle_affine(Geom::Affine const &);
+ virtual double complexity(Geom::Affine const &ctm);
+ virtual bool uses_background();
virtual void set_input(int input);
virtual void set_input(int input, int slot);
diff --git a/src/display/nr-filter-morphology.cpp b/src/display/nr-filter-morphology.cpp
index c79667d3e..9e43d01f3 100644
--- a/src/display/nr-filter-morphology.cpp
+++ b/src/display/nr-filter-morphology.cpp
@@ -158,6 +158,13 @@ void FilterMorphology::area_enlarge(NRRectL &area, Geom::Affine const &trans)
area.y1 += enlarge_y;
}
+double FilterMorphology::complexity(Geom::Affine const &trans)
+{
+ int enlarge_x = ceil(xradius * trans.expansionX());
+ int enlarge_y = ceil(yradius * trans.expansionY());
+ return enlarge_x * enlarge_y;
+}
+
void FilterMorphology::set_operator(FilterMorphologyOperator &o){
Operator = o;
}
diff --git a/src/display/nr-filter-morphology.h b/src/display/nr-filter-morphology.h
index 5924085d9..512eca83c 100644
--- a/src/display/nr-filter-morphology.h
+++ b/src/display/nr-filter-morphology.h
@@ -33,6 +33,8 @@ public:
virtual void render_cairo(FilterSlot &slot);
virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans);
+ virtual double complexity(Geom::Affine const &ctm);
+
void set_operator(FilterMorphologyOperator &o);
void set_xradius(double x);
void set_yradius(double y);
diff --git a/src/display/nr-filter-offset.cpp b/src/display/nr-filter-offset.cpp
index 3b0f83841..db8b6d92a 100644
--- a/src/display/nr-filter-offset.cpp
+++ b/src/display/nr-filter-offset.cpp
@@ -85,6 +85,11 @@ void FilterOffset::area_enlarge(NRRectL &area, Geom::Affine const &trans)
}
}
+double FilterOffset::complexity(Geom::Affine const &)
+{
+ return 1.02;
+}
+
} /* namespace Filters */
} /* namespace Inkscape */
diff --git a/src/display/nr-filter-offset.h b/src/display/nr-filter-offset.h
index 09c57f803..841be6008 100644
--- a/src/display/nr-filter-offset.h
+++ b/src/display/nr-filter-offset.h
@@ -29,6 +29,7 @@ public:
virtual void render_cairo(FilterSlot &slot);
virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans);
virtual bool can_handle_affine(Geom::Affine const &);
+ virtual double complexity(Geom::Affine const &ctm);
void set_dx(double amount);
void set_dy(double amount);
diff --git a/src/display/nr-filter-primitive.cpp b/src/display/nr-filter-primitive.cpp
index 539e3e952..0a445b9e6 100644
--- a/src/display/nr-filter-primitive.cpp
+++ b/src/display/nr-filter-primitive.cpp
@@ -161,10 +161,6 @@ Geom::Rect FilterPrimitive::filter_primitive_area(FilterUnits const &units)
return area;
}
-FilterTraits FilterPrimitive::get_input_traits() {
- return TRAIT_ANYTHING;
-}
-
} /* namespace Filters */
} /* namespace Inkscape */
diff --git a/src/display/nr-filter-primitive.h b/src/display/nr-filter-primitive.h
index ebecb91ec..501d76447 100644
--- a/src/display/nr-filter-primitive.h
+++ b/src/display/nr-filter-primitive.h
@@ -12,6 +12,7 @@
#define SEEN_NR_FILTER_PRIMITIVE_H
#include <2geom/forward.h>
+#include "display/nr-filter-types.h"
#include "svg/svg-length.h"
struct NRRectL;
@@ -22,24 +23,6 @@ namespace Filters {
class FilterSlot;
class FilterUnits;
-/*
- * Different filter effects need different types of inputs. This is what
- * traits are used for: one can specify, what special restrictions
- * there are for inputs.
- *
- * Example: gaussian blur requires that x- and y-axis of input image
- * are paraller to blurred object's x- and y-axis, respectively.
- * Otherwise blur wouldn't rotate with the object.
- *
- * Values here should be powers of two, so these can be used as bitfield.
- * That is: any combination ef existing traits can be specified. (excluding
- * TRAIT_ANYTHING, which is alias for no traits defined)
- */
-enum FilterTraits {
- TRAIT_ANYTHING = 0,
- TRAIT_PARALLER = 1
-};
-
class FilterPrimitive {
public:
FilterPrimitive();
@@ -81,6 +64,18 @@ public:
*/
virtual void set_output(int slot);
+ // returns cache score factor, reflecting the cost of rendering this filter
+ // this should return how many times slower this primitive is that normal rendering
+ virtual double complexity(Geom::Affine const &/*ctm*/) { return 1.0; }
+
+ virtual bool uses_background() {
+ if (_input == NR_FILTER_BACKGROUNDIMAGE || _input == NR_FILTER_BACKGROUNDALPHA) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
/**
* Sets the filter primitive subregion. Passing an unset length
* (length._set == false) WILL change the parameter as it is
@@ -103,14 +98,6 @@ public:
*/
Geom::Rect filter_primitive_area(FilterUnits const &units);
- /**
- * Queries the filter, which traits it needs from its input buffers.
- * At the time of writing this, only one trait was needed, having
- * user coordinate system and input pixelblock coordinates paraller to
- * each other.
- */
- virtual FilterTraits get_input_traits();
-
/** @brief Indicate whether the filter primitive can handle the given affine.
*
* Results of some filter primitives depend on the coordinate system used when rendering.
@@ -121,7 +108,7 @@ public:
* When any filter returns false, filter rendering is performed on an intermediate surface
* with edges parallel to the axes of the user coordinate system. This means
* the matrices from FilterUnits will contain at most a (possibly non-uniform) scale
- * and a translation. When all primitives of the filter return false, the rendering is
+ * and a translation. When all primitives of the filter return true, the rendering is
* performed in display coordinate space and no intermediate surface is used. */
virtual bool can_handle_affine(Geom::Affine const &) { return false; }
diff --git a/src/display/nr-filter-slot.cpp b/src/display/nr-filter-slot.cpp
index 3464fda66..4f7a8849e 100644
--- a/src/display/nr-filter-slot.cpp
+++ b/src/display/nr-filter-slot.cpp
@@ -16,7 +16,7 @@
#include <2geom/transforms.h>
#include "display/cairo-utils.h"
-#include "display/nr-arena-item.h"
+#include "display/drawing-context.h"
#include "display/nr-filter-types.h"
#include "display/nr-filter-gaussian.h"
#include "display/nr-filter-slot.h"
@@ -25,13 +25,13 @@
namespace Inkscape {
namespace Filters {
-FilterSlot::FilterSlot(NRArenaItem *item, cairo_t *bgct, NRRectL const *bgarea,
- cairo_surface_t *graphic, NRRectL const *graphicarea, FilterUnits const &u)
+FilterSlot::FilterSlot(DrawingItem *item, DrawingContext *bgct,
+ DrawingContext &graphic, FilterUnits const &u)
: _item(item)
- , _source_graphic(graphic)
- , _background_ct(bgct)
- , _source_graphic_area(graphicarea)
- , _background_area(bgarea)
+ , _source_graphic(graphic.rawTarget())
+ , _background_ct(bgct ? bgct->raw() : NULL)
+ , _source_graphic_area(graphic.targetLogicalBounds().roundOutwards()) // fixme
+ , _background_area(bgct ? bgct->targetLogicalBounds().roundOutwards() : Geom::IntRect()) // fixme
, _units(u)
, _last_out(NR_FILTER_SOURCEGRAPHIC)
, filterquality(FILTER_QUALITY_BEST)
@@ -41,19 +41,15 @@ FilterSlot::FilterSlot(NRArenaItem *item, cairo_t *bgct, NRRectL const *bgarea,
using Geom::Y;
// compute slot bbox
- Geom::Rect bbox(
- Geom::Point(_source_graphic_area->x0, _source_graphic_area->y0),
- Geom::Point(_source_graphic_area->x1, _source_graphic_area->y1));
-
Geom::Affine trans = _units.get_matrix_display2pb();
- Geom::Rect bbox_trans = bbox * trans;
+ Geom::Rect bbox_trans = graphic.targetLogicalBounds() * trans;
Geom::Point min = bbox_trans.min();
_slot_x = min[X];
_slot_y = min[Y];
if (trans.isTranslation()) {
- _slot_w = _source_graphic_area->x1 - _source_graphic_area->x0;
- _slot_h = _source_graphic_area->y1 - _source_graphic_area->y0;
+ _slot_w = _source_graphic_area.width();
+ _slot_h = _source_graphic_area.height();
} else {
_slot_w = ceil(bbox_trans.width());
_slot_h = ceil(bbox_trans.height());
@@ -143,7 +139,7 @@ cairo_surface_t *FilterSlot::_get_transformed_source_graphic()
cairo_translate(tsg_ct, -_slot_x, -_slot_y);
ink_cairo_transform(tsg_ct, trans);
- cairo_translate(tsg_ct, _source_graphic_area->x0, _source_graphic_area->y0);
+ cairo_translate(tsg_ct, _source_graphic_area.left(), _source_graphic_area.top());
cairo_set_source_surface(tsg_ct, _source_graphic, 0, 0);
cairo_set_operator(tsg_ct, CAIRO_OPERATOR_SOURCE);
cairo_paint(tsg_ct);
@@ -156,19 +152,25 @@ cairo_surface_t *FilterSlot::_get_transformed_background()
{
Geom::Affine trans = _units.get_matrix_display2pb();
- cairo_surface_t *bg = cairo_get_group_target(_background_ct);
- cairo_surface_t *tbg = cairo_surface_create_similar(
- bg, cairo_surface_get_content(bg),
- _slot_w, _slot_h);
- cairo_t *tbg_ct = cairo_create(tbg);
+ cairo_surface_t *tbg;
- cairo_translate(tbg_ct, -_slot_x, -_slot_y);
- ink_cairo_transform(tbg_ct, trans);
- cairo_translate(tbg_ct, _background_area->x0, _background_area->y0);
- cairo_set_source_surface(tbg_ct, bg, 0, 0);
- cairo_set_operator(tbg_ct, CAIRO_OPERATOR_SOURCE);
- cairo_paint(tbg_ct);
- cairo_destroy(tbg_ct);
+ if (_background_ct) {
+ cairo_surface_t *bg = cairo_get_group_target(_background_ct);
+ tbg = cairo_surface_create_similar(
+ bg, cairo_surface_get_content(bg),
+ _slot_w, _slot_h);
+ cairo_t *tbg_ct = cairo_create(tbg);
+
+ cairo_translate(tbg_ct, -_slot_x, -_slot_y);
+ ink_cairo_transform(tbg_ct, trans);
+ cairo_translate(tbg_ct, _background_area.left(), _background_area.top());
+ cairo_set_source_surface(tbg_ct, bg, 0, 0);
+ cairo_set_operator(tbg_ct, CAIRO_OPERATOR_SOURCE);
+ cairo_paint(tbg_ct);
+ cairo_destroy(tbg_ct);
+ } else {
+ tbg = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, _slot_w, _slot_h);
+ }
return tbg;
}
@@ -184,11 +186,11 @@ cairo_surface_t *FilterSlot::get_result(int res)
cairo_surface_t *r = cairo_surface_create_similar(_source_graphic,
cairo_surface_get_content(_source_graphic),
- _source_graphic_area->x1 - _source_graphic_area->x0,
- _source_graphic_area->y1 - _source_graphic_area->y0);
+ _source_graphic_area.width(),
+ _source_graphic_area.height());
cairo_t *r_ct = cairo_create(r);
- cairo_translate(r_ct, -_source_graphic_area->x0, -_source_graphic_area->y0);
+ cairo_translate(r_ct, -_source_graphic_area.left(), -_source_graphic_area.top());
ink_cairo_transform(r_ct, trans);
cairo_translate(r_ct, _slot_x, _slot_y);
cairo_set_source_surface(r_ct, getcairo(res), 0, 0);
diff --git a/src/display/nr-filter-slot.h b/src/display/nr-filter-slot.h
index 3b08743ed..d41b5180b 100644
--- a/src/display/nr-filter-slot.h
+++ b/src/display/nr-filter-slot.h
@@ -19,16 +19,17 @@
#include "display/nr-filter-types.h"
#include "display/nr-filter-units.h"
-struct NRArenaItem;
-
namespace Inkscape {
+class DrawingContext;
+class DrawingItem;
+
namespace Filters {
class FilterSlot {
public:
/** Creates a new FilterSlot object. */
- FilterSlot(NRArenaItem *item, cairo_t *bgct, NRRectL const *bgarea,
- cairo_surface_t *graphic, NRRectL const *graphicarea, FilterUnits const &u);
+ FilterSlot(DrawingItem *item, DrawingContext *bgct,
+ DrawingContext &graphic, FilterUnits const &u);
/** Destroys the FilterSlot object and all its contents */
virtual ~FilterSlot();
@@ -66,12 +67,12 @@ public:
FilterUnits const &get_units() const { return _units; }
Geom::Rect get_slot_area() const;
- NRRectL const &get_sg_area() const { return *_source_graphic_area; }
+ NRRectL get_sg_area() const { NRRectL ret(_source_graphic_area); return ret; }
private:
typedef std::map<int, cairo_surface_t *> SlotMap;
SlotMap _slots;
- NRArenaItem *_item;
+ DrawingItem *_item;
//Geom::Rect _source_bbox; ///< bounding box of source graphic surface
//Geom::Rect _intermediate_bbox; ///< bounding box of intermediate surfaces
@@ -81,8 +82,8 @@ private:
double _slot_x, _slot_y;
cairo_surface_t *_source_graphic;
cairo_t *_background_ct;
- NRRectL const *_source_graphic_area;
- NRRectL const *_background_area; ///< needed to extract background
+ Geom::IntRect _source_graphic_area;
+ Geom::IntRect _background_area; ///< needed to extract background
FilterUnits const &_units;
int _last_out;
FilterQuality filterquality;
diff --git a/src/display/nr-filter-specularlighting.cpp b/src/display/nr-filter-specularlighting.cpp
index 2e5f69d65..c28fd485a 100644
--- a/src/display/nr-filter-specularlighting.cpp
+++ b/src/display/nr-filter-specularlighting.cpp
@@ -174,136 +174,6 @@ void FilterSpecularLighting::render_cairo(FilterSlot &slot)
cairo_surface_destroy(out);
}
-/*
-int FilterSpecularLighting::render(FilterSlot &slot, FilterUnits const &units) {
- NRPixBlock *in = slot.get(_input);
- if (!in) {
- g_warning("Missing source image for feSpecularLighting (in=%d)", _input);
- return 1;
- }
-
- NRPixBlock *out = new NRPixBlock;
-
- //Fvector *L = NULL; //vector to the light
-
- int w = in->area.x1 - in->area.x0;
- int h = in->area.y1 - in->area.y0;
- int x0 = in->area.x0;
- int y0 = in->area.y0;
- int i, j;
- //As long as FilterRes and kernel unit is not supported we hardcode the
- //default value
- int dx = 1; //TODO setup
- int dy = 1; //TODO setup
- //surface scale
- Geom::Affine trans = units.get_matrix_primitiveunits2pb();
- gdouble ss = surfaceScale * trans[0];
- gdouble ks = specularConstant; //diffuse lighting constant
- NR::Fvector L, N, LC, H;
- gdouble inter;
-
- nr_pixblock_setup_fast(out, NR_PIXBLOCK_MODE_R8G8B8A8N,
- in->area.x0, in->area.y0, in->area.x1, in->area.y1,
- true);
- unsigned char *data_i = NR_PIXBLOCK_PX (in);
- unsigned char *data_o = NR_PIXBLOCK_PX (out);
- //No light, nothing to do
- switch (light_type) {
- case DISTANT_LIGHT:
- //the light vector is constant
- {
- DistantLight *dl = new DistantLight(light.distant, lighting_color);
- dl->light_vector(L);
- dl->light_components(LC);
- NR::normalized_sum(H, L, NR::EYE_VECTOR);
- //finish the work
- for (i = 0, j = 0; i < w*h; i++) {
- NR::compute_surface_normal(N, ss, in, i / w, i % w, dx, dy);
- COMPUTE_INTER(inter, N, H, ks, specularExponent);
-
- data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_RED]); // CLAMP includes rounding!
- data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_GREEN]);
- data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_BLUE]);
- data_o[j] = MAX(MAX(data_o[j-3], data_o[j-2]), data_o[j-1]);
- ++j;
- }
- out->empty = FALSE;
- delete dl;
- }
- break;
- case POINT_LIGHT:
- {
- PointLight *pl = new PointLight(light.point, lighting_color, trans);
- pl->light_components(LC);
- //TODO we need a reference to the filter to determine primitiveUnits
- //if objectBoundingBox is used, use a different matrix for light_vector
- // UPDATE: trans is now correct matrix from primitiveUnits to
- // pixblock coordinates
- //finish the work
- for (i = 0, j = 0; i < w*h; i++) {
- NR::compute_surface_normal(N, ss, in, i / w, i % w, dx, dy);
- pl->light_vector(L,
- i % w + x0,
- i / w + y0,
- ss * (double) data_i[4*i+3]/ 255);
- NR::normalized_sum(H, L, NR::EYE_VECTOR);
- COMPUTE_INTER(inter, N, H, ks, specularExponent);
-
- data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_RED]);
- data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_GREEN]);
- data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_BLUE]);
- data_o[j] = MAX(MAX(data_o[j-3], data_o[j-2]), data_o[j-1]);
- ++j;
- }
- out->empty = FALSE;
- delete pl;
- }
- break;
- case SPOT_LIGHT:
- {
- SpotLight *sl = new SpotLight(light.spot, lighting_color, trans);
- //TODO we need a reference to the filter to determine primitiveUnits
- //if objectBoundingBox is used, use a different matrix for light_vector
- // UPDATE: trans is now correct matrix from primitiveUnits to
- // pixblock coordinates
- //finish the work
- for (i = 0, j = 0; i < w*h; i++) {
- NR::compute_surface_normal(N, ss, in, i / w, i % w, dx, dy);
- sl->light_vector(L,
- i % w + x0,
- i / w + y0,
- ss * (double) data_i[4*i+3]/ 255);
- sl->light_components(LC, L);
- NR::normalized_sum(H, L, NR::EYE_VECTOR);
- COMPUTE_INTER(inter, N, H, ks, specularExponent);
-
- data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_RED]);
- data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_GREEN]);
- data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_BLUE]);
- data_o[j] = MAX(MAX(data_o[j-3], data_o[j-2]), data_o[j-1]);
- ++j;
- }
- out->empty = FALSE;
- delete sl;
- }
- break;
- //else unknown light source, doing nothing
- case NO_LIGHT:
- default:
- {
- if (light_type != NO_LIGHT)
- g_warning("unknown light source %d", light_type);
- out->empty = false;
- }
- }
-
- //finishing
- slot.set(_output, out);
- //nr_pixblock_release(in);
- //delete in;
- return 0;
-}*/
-
void FilterSpecularLighting::area_enlarge(NRRectL &area, Geom::Affine const & /*trans*/)
{
// TODO: support kernelUnitLength
@@ -314,6 +184,11 @@ void FilterSpecularLighting::area_enlarge(NRRectL &area, Geom::Affine const & /*
area.y1 += 1;
}
+double FilterSpecularLighting::complexity(Geom::Affine const &)
+{
+ return 9.0;
+}
+
} /* namespace Filters */
} /* namespace Inkscape */
diff --git a/src/display/nr-filter-specularlighting.h b/src/display/nr-filter-specularlighting.h
index 2fcb02588..8471b70b0 100644
--- a/src/display/nr-filter-specularlighting.h
+++ b/src/display/nr-filter-specularlighting.h
@@ -31,8 +31,10 @@ public:
FilterSpecularLighting();
static FilterPrimitive *create();
virtual ~FilterSpecularLighting();
+
virtual void render_cairo(FilterSlot &slot);
virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans);
+ virtual double complexity(Geom::Affine const &ctm);
union {
SPFeDistantLight *distant;
diff --git a/src/display/nr-filter-tile.cpp b/src/display/nr-filter-tile.cpp
index b88386638..4aadde2aa 100644
--- a/src/display/nr-filter-tile.cpp
+++ b/src/display/nr-filter-tile.cpp
@@ -45,6 +45,11 @@ void FilterTile::area_enlarge(NRRectL &/*area*/, Geom::Affine const &/*trans*/)
{
}
+double FilterTile::complexity(Geom::Affine const &)
+{
+ return 1.0;
+}
+
} /* namespace Filters */
} /* namespace Inkscape */
diff --git a/src/display/nr-filter-tile.h b/src/display/nr-filter-tile.h
index 5c0a3e553..37e257f79 100644
--- a/src/display/nr-filter-tile.h
+++ b/src/display/nr-filter-tile.h
@@ -27,6 +27,7 @@ public:
virtual void render_cairo(FilterSlot &slot);
virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans);
+ virtual double complexity(Geom::Affine const &ctm);
};
} /* namespace Filters */
diff --git a/src/display/nr-filter-turbulence.cpp b/src/display/nr-filter-turbulence.cpp
index 60d5ce872..f065ded11 100644
--- a/src/display/nr-filter-turbulence.cpp
+++ b/src/display/nr-filter-turbulence.cpp
@@ -388,6 +388,11 @@ void FilterTurbulence::render_cairo(FilterSlot &slot)
cairo_surface_destroy(out);
}
+double FilterTurbulence::complexity(Geom::Affine const &)
+{
+ return 5.0;
+}
+
} /* namespace Filters */
} /* namespace Inkscape */
diff --git a/src/display/nr-filter-turbulence.h b/src/display/nr-filter-turbulence.h
index 8d3639543..0b451d355 100644
--- a/src/display/nr-filter-turbulence.h
+++ b/src/display/nr-filter-turbulence.h
@@ -45,6 +45,8 @@ public:
virtual ~FilterTurbulence();
virtual void render_cairo(FilterSlot &slot);
+ virtual double complexity(Geom::Affine const &ctm);
+ virtual bool uses_background() { return false; }
void set_baseFrequency(int axis, double freq);
void set_numOctaves(int num);
diff --git a/src/display/nr-filter-units.cpp b/src/display/nr-filter-units.cpp
index a8686545a..baf4af45d 100644
--- a/src/display/nr-filter-units.cpp
+++ b/src/display/nr-filter-units.cpp
@@ -71,10 +71,10 @@ Geom::Affine FilterUnits::get_matrix_user2pb() const {
Geom::Affine u2pb = ctm;
if (paraller_axis || !automatic_resolution) {
- u2pb[0] = resolution_x / (filter_area->max()[X] - filter_area->min()[X]);
+ u2pb[0] = resolution_x / filter_area->width();
u2pb[1] = 0;
u2pb[2] = 0;
- u2pb[3] = resolution_y / (filter_area->max()[Y] - filter_area->min()[Y]);
+ u2pb[3] = resolution_y / filter_area->height();
u2pb[4] = ctm[4];
u2pb[5] = ctm[5];
}
diff --git a/src/display/nr-filter.cpp b/src/display/nr-filter.cpp
index 963d98654..450ce689d 100644
--- a/src/display/nr-filter.cpp
+++ b/src/display/nr-filter.cpp
@@ -38,8 +38,9 @@
#include "display/nr-filter-tile.h"
#include "display/nr-filter-turbulence.h"
-#include "display/nr-arena.h"
-#include "display/nr-arena-item.h"
+#include "display/drawing.h"
+#include "display/drawing-item.h"
+#include "display/drawing-context.h"
#include <2geom/affine.h>
#include <2geom/rect.h>
#include "svg/svg-length.h"
@@ -96,50 +97,38 @@ Filter::~Filter()
}
-int Filter::render(NRArenaItem const *item, cairo_t *bgct, NRRectL const *bgarea, cairo_t *graphic, NRRectL const *area)
+int Filter::render(Inkscape::DrawingItem const *item, DrawingContext &graphic, DrawingContext *bgct)
{
if (_primitive.empty()) {
// when no primitives are defined, clear source graphic
- cairo_set_source_rgba(graphic, 0,0,0,0);
- cairo_set_operator(graphic, CAIRO_OPERATOR_SOURCE);
- cairo_paint(graphic);
- cairo_set_operator(graphic, CAIRO_OPERATOR_OVER);
+ graphic.setSource(0,0,0,0);
+ graphic.setOperator(CAIRO_OPERATOR_SOURCE);
+ graphic.paint();
+ graphic.setOperator(CAIRO_OPERATOR_OVER);
return 1;
}
- FilterQuality const filterquality = (FilterQuality)item->arena->filterquality;
- int const blurquality = item->arena->blurquality;
+ FilterQuality const filterquality = (FilterQuality)item->drawing().filterQuality();
+ int const blurquality = item->drawing().blurQuality();
- Geom::Affine trans = item->ctm;
+ Geom::Affine trans = item->ctm();
- Geom::Rect item_bbox;
- {
- Geom::OptRect maybe_bbox = item->item_bbox;
- if (maybe_bbox.isEmpty()) {
- // Code below needs a bounding box
- return 1;
- }
- item_bbox = *maybe_bbox;
- }
- if (item_bbox.hasZeroArea()) {
- // It's no use to try and filter an empty object.
- return 1;
- }
- Geom::Rect filter_area = filter_effect_area(item_bbox);
+ Geom::OptRect filter_area = filter_effect_area(item->itemBounds());
+ if (!filter_area) return 1;
FilterUnits units(_filter_units, _primitive_units);
units.set_ctm(trans);
- units.set_item_bbox(item_bbox);
- units.set_filter_area(filter_area);
+ units.set_item_bbox(item->itemBounds());
+ units.set_filter_area(*filter_area);
std::pair<double,double> resolution
- = _filter_resolution(filter_area, trans, filterquality);
+ = _filter_resolution(*filter_area, trans, filterquality);
if (!(resolution.first > 0 && resolution.second > 0)) {
// zero resolution - clear source graphic and return
- cairo_set_source_rgba(graphic, 0,0,0,0);
- cairo_set_operator(graphic, CAIRO_OPERATOR_SOURCE);
- cairo_paint(graphic);
- cairo_set_operator(graphic, CAIRO_OPERATOR_OVER);
+ graphic.setSource(0,0,0,0);
+ graphic.setOperator(CAIRO_OPERATOR_SOURCE);
+ graphic.paint();
+ graphic.setOperator(CAIRO_OPERATOR_OVER);
return 1;
}
@@ -160,7 +149,7 @@ int Filter::render(NRArenaItem const *item, cairo_t *bgct, NRRectL const *bgarea
}
}
- FilterSlot slot(const_cast<NRArenaItem*>(item), bgct, bgarea, cairo_get_group_target(graphic), area, units);
+ FilterSlot slot(const_cast<Inkscape::DrawingItem*>(item), bgct, graphic, units);
slot.set_quality(filterquality);
slot.set_blurquality(blurquality);
@@ -168,11 +157,12 @@ int Filter::render(NRArenaItem const *item, cairo_t *bgct, NRRectL const *bgarea
_primitive[i]->render_cairo(slot);
}
+ Geom::Point origin = graphic.targetLogicalBounds().min();
cairo_surface_t *result = slot.get_result(_output_slot);
- cairo_set_source_surface(graphic, result, area->x0, area->y0);
- cairo_set_operator(graphic, CAIRO_OPERATOR_SOURCE);
- cairo_paint(graphic);
- cairo_set_operator(graphic, CAIRO_OPERATOR_OVER);
+ graphic.setSource(result, origin[Geom::X], origin[Geom::Y]);
+ graphic.setOperator(CAIRO_OPERATOR_SOURCE);
+ graphic.paint();
+ graphic.setOperator(CAIRO_OPERATOR_OVER);
cairo_surface_destroy(result);
return 0;
@@ -186,10 +176,12 @@ void Filter::set_primitive_units(SPFilterUnits unit) {
_primitive_units = unit;
}
-void Filter::area_enlarge(NRRectL &bbox, NRArenaItem const *item) const {
+void Filter::area_enlarge(Geom::IntRect &bbox, Inkscape::DrawingItem const *item) const {
+ NRRectL b(bbox);
for (unsigned i = 0 ; i < _primitive.size() ; i++) {
- if (_primitive[i]) _primitive[i]->area_enlarge(bbox, item->ctm);
+ if (_primitive[i]) _primitive[i]->area_enlarge(b, item->ctm());
}
+ bbox = *b.upgrade_2geom();
/*
TODO: something. See images at the bottom of filters.svg with medium-low
@@ -204,7 +196,7 @@ void Filter::area_enlarge(NRRectL &bbox, NRArenaItem const *item) const {
}
Geom::Rect item_bbox;
- Geom::OptRect maybe_bbox = item->item_bbox;
+ Geom::OptRect maybe_bbox = item->itemBounds();
if (maybe_bbox.isEmpty()) {
// Code below needs a bounding box
return;
@@ -212,9 +204,9 @@ void Filter::area_enlarge(NRRectL &bbox, NRArenaItem const *item) const {
item_bbox = *maybe_bbox;
std::pair<double,double> res_low
- = _filter_resolution(item_bbox, item->ctm, filterquality);
+ = _filter_resolution(item_bbox, item->ctm(), filterquality);
//std::pair<double,double> res_full
- // = _filter_resolution(item_bbox, item->ctm, FILTER_QUALITY_BEST);
+ // = _filter_resolution(item_bbox, item->ctm(), FILTER_QUALITY_BEST);
double pixels_per_block = fmax(item_bbox.width() / res_low.first,
item_bbox.height() / res_low.second);
bbox.x0 -= (int)pixels_per_block;
@@ -224,39 +216,36 @@ void Filter::area_enlarge(NRRectL &bbox, NRArenaItem const *item) const {
*/
}
-void Filter::compute_drawbox(NRArenaItem const *item, NRRectL &item_bbox) {
- // Modifying empty bounding boxes confuses rest of the renderer, so
- // let's not do that.
- if (item_bbox.x0 > item_bbox.x1 || item_bbox.y0 > item_bbox.y1) return;
-
- Geom::Point min(item_bbox.x0, item_bbox.y0);
- Geom::Point max(item_bbox.x1, item_bbox.y1);
- Geom::Rect tmp_bbox(min, max);
+Geom::OptIntRect Filter::compute_drawbox(Inkscape::DrawingItem const *item, Geom::OptRect const &item_bbox) {
- Geom::Rect enlarged = filter_effect_area(tmp_bbox);
- enlarged = enlarged * item->ctm;
+ Geom::OptRect enlarged = filter_effect_area(item_bbox);
+ if (enlarged) {
+ *enlarged *= item->ctm();
- item_bbox.x0 = floor(enlarged.min()[X]);
- item_bbox.y0 = floor(enlarged.min()[Y]);
- item_bbox.x1 = ceil(enlarged.max()[X]);
- item_bbox.y1 = ceil(enlarged.max()[Y]);
+ Geom::OptIntRect ret(enlarged->roundOutwards());
+ return ret;
+ } else {
+ return Geom::OptIntRect();
+ }
}
-Geom::Rect Filter::filter_effect_area(Geom::Rect const &bbox)
+Geom::OptRect Filter::filter_effect_area(Geom::OptRect const &bbox)
{
Geom::Point minp, maxp;
- double len_x = bbox.width();
- double len_y = bbox.height();
+ double len_x = bbox ? bbox->width() : 0;
+ double len_y = bbox ? bbox->height() : 0;
/* TODO: fetch somehow the object ex and em lengths */
_region_x.update(12, 6, len_x);
_region_y.update(12, 6, len_y);
_region_width.update(12, 6, len_x);
_region_height.update(12, 6, len_y);
if (_filter_units == SP_FILTER_UNITS_OBJECTBOUNDINGBOX) {
+ if (!bbox) return Geom::OptRect();
+
if (_region_x.unit == SVGLength::PERCENT) {
- minp[X] = bbox.min()[X] + _region_x.computed;
+ minp[X] = bbox->left() + _region_x.computed;
} else {
- minp[X] = bbox.min()[X] + _region_x.computed * len_x;
+ minp[X] = bbox->left() + _region_x.computed * len_x;
}
if (_region_width.unit == SVGLength::PERCENT) {
maxp[X] = minp[X] + _region_width.computed;
@@ -265,9 +254,9 @@ Geom::Rect Filter::filter_effect_area(Geom::Rect const &bbox)
}
if (_region_y.unit == SVGLength::PERCENT) {
- minp[Y] = bbox.min()[Y] + _region_y.computed;
+ minp[Y] = bbox->top() + _region_y.computed;
} else {
- minp[Y] = bbox.min()[Y] + _region_y.computed * len_y;
+ minp[Y] = bbox->top() + _region_y.computed * len_y;
}
if (_region_height.unit == SVGLength::PERCENT) {
maxp[Y] = minp[Y] + _region_height.computed;
@@ -283,10 +272,32 @@ Geom::Rect Filter::filter_effect_area(Geom::Rect const &bbox)
} else {
g_warning("Error in Inkscape::Filters::Filter::filter_effect_area: unrecognized value of _filter_units");
}
- Geom::Rect area(minp, maxp);
+ Geom::OptRect area(minp, maxp);
return area;
}
+double Filter::complexity(Geom::Affine const &ctm)
+{
+ double factor = 1.0;
+ for (unsigned i = 0 ; i < _primitive.size() ; i++) {
+ if (_primitive[i]) {
+ double f = _primitive[i]->complexity(ctm);
+ factor += (f - 1.0);
+ }
+ }
+ return factor;
+}
+
+bool Filter::uses_background()
+{
+ for (unsigned i = 0 ; i < _primitive.size() ; i++) {
+ if (_primitive[i] && _primitive[i]->uses_background()) {
+ return true;
+ }
+ }
+ return false;
+}
+
/* Constructor table holds pointers to static methods returning filter
* primitives. This table is indexed with FilterPrimitiveType, so that
* for example method in _constructor[NR_FILTER_GAUSSIANBLUR]
diff --git a/src/display/nr-filter.h b/src/display/nr-filter.h
index e1d4c10e5..32e1df60b 100644
--- a/src/display/nr-filter.h
+++ b/src/display/nr-filter.h
@@ -21,19 +21,20 @@
#include "sp-filter-units.h"
#include "gc-managed.h"
-struct NRArenaItem;
-
namespace Inkscape {
+class DrawingContext;
+class DrawingItem;
+
namespace Filters {
-class Filter : public Inkscape::GC::Managed<> {
+class Filter {
public:
/** Given background state from @a bgct and an intermediate rendering from the surface
* backing @a graphic, modify the contents of the surface backing @a graphic to represent
* the results of filter rendering. @a bgarea and @a area specify bounding boxes
* of both surfaces in world coordinates; Cairo contexts are assumed to be in default state
* (0,0 = surface origin, no path, OVER operator) */
- int render(NRArenaItem const *item, cairo_t *bgct, NRRectL const *bgarea, cairo_t *graphic, NRRectL const *area);
+ int render(Inkscape::DrawingItem const *item, DrawingContext &graphic, DrawingContext *bgct);
/**
* Creates a new filter primitive under this filter object.
@@ -149,19 +150,25 @@ public:
* to be rendered so that after filtering, the original area is
* drawn correctly.
*/
- void area_enlarge(NRRectL &area, NRArenaItem const *item) const;
+ void area_enlarge(Geom::IntRect &area, Inkscape::DrawingItem const *item) const;
/**
* Given an item bounding box (in user coords), this function enlarges it
* to contain the filter effects region and transforms it to screen
* coordinates
*/
- void compute_drawbox(NRArenaItem const *item, NRRectL &item_bbox);
+ Geom::OptIntRect compute_drawbox(Inkscape::DrawingItem const *item, Geom::OptRect const &item_bbox);
/**
* Returns the filter effects area in user coordinate system.
* The given bounding box should be a bounding box as specified in
* SVG standard and in user coordinate system.
*/
- Geom::Rect filter_effect_area(Geom::Rect const &bbox);
+ Geom::OptRect filter_effect_area(Geom::OptRect const &bbox);
+
+ // returns cache score factor
+ double complexity(Geom::Affine const &ctm);
+
+ // says whether the filter accesses any of the background images
+ bool uses_background();
/** Creates a new filter with space for one filter element */
Filter();
diff --git a/src/display/nr-style.cpp b/src/display/nr-style.cpp
index 72fa0c444..fa5dd0d98 100644
--- a/src/display/nr-style.cpp
+++ b/src/display/nr-style.cpp
@@ -13,6 +13,8 @@
#include "style.h"
#include "sp-paint-server.h"
#include "display/canvas-bpath.h" // contains SPStrokeJoinType, SPStrokeCapType etc. (WTF!)
+#include "display/drawing-context.h"
+#include "libnr/nr-rect.h"
void NRStyle::Paint::clear()
{
@@ -142,14 +144,15 @@ void NRStyle::set(SPStyle *style)
update();
}
-bool NRStyle::prepareFill(cairo_t *ct, NRRect *paintbox)
+bool NRStyle::prepareFill(Inkscape::DrawingContext &ct, Geom::OptRect const &paintbox)
{
// update fill pattern
if (!fill_pattern) {
switch (fill.type) {
- case PAINT_SERVER:
- fill_pattern = sp_paint_server_create_pattern(fill.server, ct, paintbox, fill.opacity);
- break;
+ case PAINT_SERVER: {
+ NRRect pb(paintbox);
+ fill_pattern = sp_paint_server_create_pattern(fill.server, ct.raw(), &pb, fill.opacity);
+ } break;
case PAINT_COLOR: {
SPColor const &c = fill.color;
fill_pattern = cairo_pattern_create_rgba(
@@ -162,19 +165,20 @@ bool NRStyle::prepareFill(cairo_t *ct, NRRect *paintbox)
return true;
}
-void NRStyle::applyFill(cairo_t *ct)
+void NRStyle::applyFill(Inkscape::DrawingContext &ct)
{
- cairo_set_source(ct, fill_pattern);
- cairo_set_fill_rule(ct, fill_rule);
+ ct.setSource(fill_pattern);
+ ct.setFillRule(fill_rule);
}
-bool NRStyle::prepareStroke(cairo_t *ct, NRRect *paintbox)
+bool NRStyle::prepareStroke(Inkscape::DrawingContext &ct, Geom::OptRect const &paintbox)
{
if (!stroke_pattern) {
switch (stroke.type) {
- case PAINT_SERVER:
- stroke_pattern = sp_paint_server_create_pattern(stroke.server, ct, paintbox, stroke.opacity);
- break;
+ case PAINT_SERVER: {
+ NRRect pb(paintbox);
+ stroke_pattern = sp_paint_server_create_pattern(stroke.server, ct.raw(), &pb, stroke.opacity);
+ } break;
case PAINT_COLOR: {
SPColor const &c = stroke.color;
stroke_pattern = cairo_pattern_create_rgba(
@@ -187,14 +191,14 @@ bool NRStyle::prepareStroke(cairo_t *ct, NRRect *paintbox)
return true;
}
-void NRStyle::applyStroke(cairo_t *ct)
+void NRStyle::applyStroke(Inkscape::DrawingContext &ct)
{
- cairo_set_source(ct, stroke_pattern);
- cairo_set_line_width(ct, stroke_width);
- cairo_set_line_cap(ct, line_cap);
- cairo_set_line_join(ct, line_join);
- cairo_set_miter_limit(ct, miter_limit);
- cairo_set_dash(ct, dash, n_dash, dash_offset);
+ ct.setSource(stroke_pattern);
+ ct.setLineWidth(stroke_width);
+ ct.setLineCap(line_cap);
+ ct.setLineJoin(line_join);
+ ct.setMiterLimit(miter_limit);
+ cairo_set_dash(ct.raw(), dash, n_dash, dash_offset); // fixme
}
void NRStyle::update()
diff --git a/src/display/nr-style.h b/src/display/nr-style.h
index e741e46b4..0ba6ce2c6 100644
--- a/src/display/nr-style.h
+++ b/src/display/nr-style.h
@@ -13,22 +13,25 @@
#define SEEN_INKSCAPE_DISPLAY_NR_ARENA_STYLE_H
#include <cairo.h>
+#include <2geom/rect.h>
#include "color.h"
class SPColor;
class SPPaintServer;
class SPStyle;
-struct NRRect;
+namespace Inkscape {
+class DrawingContext;
+}
struct NRStyle {
NRStyle();
~NRStyle();
void set(SPStyle *);
- bool prepareFill(cairo_t *ct, NRRect *paintbox);
- bool prepareStroke(cairo_t *ct, NRRect *paintbox);
- void applyFill(cairo_t *ct);
- void applyStroke(cairo_t *ct);
+ bool prepareFill(Inkscape::DrawingContext &ct, Geom::OptRect const &paintbox);
+ bool prepareStroke(Inkscape::DrawingContext &ct, Geom::OptRect const &paintbox);
+ void applyFill(Inkscape::DrawingContext &ct);
+ void applyStroke(Inkscape::DrawingContext &ct);
void update();
enum PaintType {
diff --git a/src/display/rendermode.h b/src/display/rendermode.h
index 8fc022bfb..cbd35de73 100644
--- a/src/display/rendermode.h
+++ b/src/display/rendermode.h
@@ -15,10 +15,10 @@ enum RenderMode {
RENDERMODE_OUTLINE
};
-enum ColorRenderMode {
- COLORRENDERMODE_NORMAL,
- COLORRENDERMODE_GRAYSCALE,
- COLORRENDERMODE_PRINT_COLORS_PREVIEW
+enum ColorMode {
+ COLORMODE_NORMAL,
+ COLORMODE_GRAYSCALE,
+ COLORMODE_PRINT_COLORS_PREVIEW
};
}
diff --git a/src/display/sp-canvas-item.h b/src/display/sp-canvas-item.h
index 4c731e56b..415c36566 100644
--- a/src/display/sp-canvas-item.h
+++ b/src/display/sp-canvas-item.h
@@ -64,7 +64,7 @@ struct _SPCanvasItemClass : public GtkObjectClass {
double (* point) (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_item);
int (* event) (SPCanvasItem *item, GdkEvent *event);
- void (* visible_area_changed) (SPCanvasItem *item, Geom::IntRect const &old_area, Geom::IntRect const &new_area);
+ void (* viewbox_changed) (SPCanvasItem *item, Geom::IntRect const &new_area);
};
SPCanvasItem *sp_canvas_item_new(SPCanvasGroup *parent, GType type, const gchar *first_arg_name, ...);
diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp
index 71f608118..7d6727ff3 100644
--- a/src/display/sp-canvas.cpp
+++ b/src/display/sp-canvas.cpp
@@ -689,7 +689,7 @@ static void sp_canvas_group_destroy (GtkObject *object);
static void sp_canvas_group_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags);
static double sp_canvas_group_point (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_item);
static void sp_canvas_group_render (SPCanvasItem *item, SPCanvasBuf *buf);
-static void sp_canvas_group_visible_area_changed (SPCanvasItem *item, Geom::IntRect const &old_area, Geom::IntRect const &new_area);
+static void sp_canvas_group_viewbox_changed (SPCanvasItem *item, Geom::IntRect const &new_area);
static SPCanvasItemClass *group_parent_class;
@@ -733,7 +733,7 @@ sp_canvas_group_class_init (SPCanvasGroupClass *klass)
item_class->update = sp_canvas_group_update;
item_class->render = sp_canvas_group_render;
item_class->point = sp_canvas_group_point;
- item_class->visible_area_changed = sp_canvas_group_visible_area_changed;
+ item_class->viewbox_changed = sp_canvas_group_viewbox_changed;
}
/**
@@ -878,15 +878,15 @@ sp_canvas_group_render (SPCanvasItem *item, SPCanvasBuf *buf)
}
static void
-sp_canvas_group_visible_area_changed (SPCanvasItem *item, Geom::IntRect const &old_area, Geom::IntRect const &new_area)
+sp_canvas_group_viewbox_changed (SPCanvasItem *item, Geom::IntRect const &new_area)
{
SPCanvasGroup *group = SP_CANVAS_GROUP (item);
for (GList *list = group->items; list; list = list->next) {
SPCanvasItem *child = (SPCanvasItem *)list->data;
if (child->flags & SP_CANVAS_ITEM_VISIBLE) {
- if (SP_CANVAS_ITEM_GET_CLASS (child)->visible_area_changed)
- SP_CANVAS_ITEM_GET_CLASS (child)->visible_area_changed (child, old_area, new_area);
+ if (SP_CANVAS_ITEM_GET_CLASS (child)->viewbox_changed)
+ SP_CANVAS_ITEM_GET_CLASS (child)->viewbox_changed (child, new_area);
}
}
}
@@ -1234,8 +1234,8 @@ sp_canvas_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
/* Schedule redraw of new region */
sp_canvas_resize_tiles(canvas,canvas->x0,canvas->y0,canvas->x0+allocation->width,canvas->y0+allocation->height);
- if (SP_CANVAS_ITEM_GET_CLASS (canvas->root)->visible_area_changed)
- SP_CANVAS_ITEM_GET_CLASS (canvas->root)->visible_area_changed (canvas->root, old_area, new_area);
+ if (SP_CANVAS_ITEM_GET_CLASS (canvas->root)->viewbox_changed)
+ SP_CANVAS_ITEM_GET_CLASS (canvas->root)->viewbox_changed (canvas->root, new_area);
if (allocation->width > widget->allocation.width) {
sp_canvas_request_redraw (canvas,
@@ -1655,6 +1655,15 @@ static void sp_canvas_paint_single_buffer(SPCanvas *canvas, int x0, int y0, int
buf.is_empty = true;
//buf.ct = gdk_cairo_create(widget->window);
+ /*
+ cairo_t *xctt = gdk_cairo_create(widget->window);
+ cairo_translate(xctt, x0 - canvas->x0, y0 - canvas->y0);
+ cairo_set_source_rgb(xctt, 1,0,0);
+ cairo_rectangle(xctt, 0, 0, x1-x0, y1-y0);
+ cairo_fill(xctt);
+ cairo_destroy(xctt);
+ //*/
+
// create temporary surface
int w = x1 - x0;
int h = y1 - y0;
@@ -2168,8 +2177,8 @@ sp_canvas_scroll_to (SPCanvas *canvas, double cx, double cy, unsigned int clear,
canvas->y0 = iy;
sp_canvas_resize_tiles (canvas, canvas->x0, canvas->y0, canvas->x0+canvas->widget.allocation.width, canvas->y0+canvas->widget.allocation.height);
- if (SP_CANVAS_ITEM_GET_CLASS (canvas->root)->visible_area_changed)
- SP_CANVAS_ITEM_GET_CLASS (canvas->root)->visible_area_changed (canvas->root, old_area, new_area);
+ if (SP_CANVAS_ITEM_GET_CLASS (canvas->root)->viewbox_changed)
+ SP_CANVAS_ITEM_GET_CLASS (canvas->root)->viewbox_changed (canvas->root, new_area);
if (!clear) {
// scrolling without zoom; redraw only the newly exposed areas
diff --git a/src/document.cpp b/src/document.cpp
index b699f8afa..72f92bd17 100644
--- a/src/document.cpp
+++ b/src/document.cpp
@@ -44,7 +44,7 @@
#include "desktop.h"
#include "dir-util.h"
-#include "display/nr-arena-item.h"
+#include "display/drawing-item.h"
#include "document-private.h"
#include "helper/units.h"
#include "inkscape-private.h"
@@ -1126,8 +1126,8 @@ SPItem *SPDocument::getItemFromListAtPointBottom(unsigned int dkey, SPGroup *gro
for ( SPObject *o = group->firstChild() ; o && !bottomMost; o = o->getNext() ) {
if ( SP_IS_ITEM(o) ) {
SPItem *item = SP_ITEM(o);
- NRArenaItem *arenaitem = item->get_arenaitem(dkey);
- if (arenaitem && nr_arena_item_invoke_pick(arenaitem, p, delta, 1) != NULL
+ Inkscape::DrawingItem *arenaitem = item->get_arenaitem(dkey);
+ if (arenaitem && arenaitem->pick(p, delta, 1) != NULL
&& (take_insensitive || item->isVisibleAndUnlocked(dkey))) {
if (g_slist_find((GSList *) list, item) != NULL) {
bottomMost = item;
@@ -1180,10 +1180,10 @@ SPItem *find_item_at_point(unsigned int dkey, SPGroup *group, Geom::Point const
}
} else {
SPItem *child = SP_ITEM(o);
- NRArenaItem *arenaitem = child->get_arenaitem(dkey);
+ Inkscape::DrawingItem *arenaitem = child->get_arenaitem(dkey);
// seen remembers the last (topmost) of items pickable at this point
- if (arenaitem && nr_arena_item_invoke_pick(arenaitem, p, delta, 1) != NULL
+ if (arenaitem && arenaitem->pick(p, delta, 1) != NULL
&& (take_insensitive || child->isVisibleAndUnlocked(dkey))) {
seen = child;
}
@@ -1214,10 +1214,10 @@ SPItem *find_group_at_point(unsigned int dkey, SPGroup *group, Geom::Point const
}
if (SP_IS_GROUP(o) && SP_GROUP(o)->effectiveLayerMode(dkey) != SPGroup::LAYER ) {
SPItem *child = SP_ITEM(o);
- NRArenaItem *arenaitem = child->get_arenaitem(dkey);
+ Inkscape::DrawingItem *arenaitem = child->get_arenaitem(dkey);
// seen remembers the last (topmost) of groups pickable at this point
- if (arenaitem && nr_arena_item_invoke_pick(arenaitem, p, delta, 1) != NULL) {
+ if (arenaitem && arenaitem->pick(p, delta, 1) != NULL) {
seen = child;
}
}
diff --git a/src/ege-adjustment-action.cpp b/src/ege-adjustment-action.cpp
index 45a44ae0c..f3009ac04 100644
--- a/src/ege-adjustment-action.cpp
+++ b/src/ege-adjustment-action.cpp
@@ -300,10 +300,11 @@ static void ege_adjustment_action_finalize( GObject* object )
action = EGE_ADJUSTMENT_ACTION( object );
- if ( action->private_data->format ) {
- g_free( action->private_data->format );
- action->private_data->format = 0;
- }
+ // g_free(NULL) does nothing
+ g_free( action->private_data->format );
+ g_free( action->private_data->selfId );
+ g_free( action->private_data->appearance );
+ g_free( action->private_data->iconId );
egeAct_free_all_descriptions( action );
diff --git a/src/ege-select-one-action.cpp b/src/ege-select-one-action.cpp
index 047a65868..d864394af 100644
--- a/src/ege-select-one-action.cpp
+++ b/src/ege-select-one-action.cpp
@@ -52,6 +52,7 @@ enum {
static void ege_select_one_action_class_init( EgeSelectOneActionClass* klass );
static void ege_select_one_action_init( EgeSelectOneAction* action );
+static void ege_select_one_action_finalize( GObject* action );
static void ege_select_one_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec );
static void ege_select_one_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec );
@@ -159,6 +160,7 @@ void ege_select_one_action_class_init( EgeSelectOneActionClass* klass )
gDataName = g_quark_from_string("ege-select1-action");
+ objClass->finalize = ege_select_one_action_finalize;
objClass->get_property = ege_select_one_action_get_property;
objClass->set_property = ege_select_one_action_set_property;
@@ -282,6 +284,19 @@ void ege_select_one_action_init( EgeSelectOneAction* action )
/* g_signal_connect( action, "notify", G_CALLBACK( fixup_labels ), NULL ); */
}
+void ege_select_one_action_finalize( GObject* object )
+{
+ EgeSelectOneAction *action = EGE_SELECT_ONE_ACTION( object );
+
+ g_free( action->private_data->iconProperty );
+ g_free( action->private_data->appearance );
+ g_free( action->private_data->selection );
+
+ if ( G_OBJECT_CLASS(gParentClass)->finalize ) {
+ (*G_OBJECT_CLASS(gParentClass)->finalize)(object);
+ }
+}
+
EgeSelectOneAction* ege_select_one_action_new( const gchar *name,
const gchar *label,
const gchar *tooltip,
diff --git a/src/extension/internal/cairo-png-out.cpp b/src/extension/internal/cairo-png-out.cpp
index f741c9f39..678a46095 100644
--- a/src/extension/internal/cairo-png-out.cpp
+++ b/src/extension/internal/cairo-png-out.cpp
@@ -27,8 +27,7 @@
#include "extension/print.h"
#include "extension/db.h"
#include "extension/output.h"
-#include "display/nr-arena.h"
-#include "display/nr-arena-item.h"
+#include "display/drawing.h"
#include "display/curve.h"
#include "display/canvas-bpath.h"
@@ -57,11 +56,11 @@ png_render_document_to_file(SPDocument *doc, gchar const *filename)
doc->ensureUpToDate();
/* Start */
- // Create new arena
+
SPItem *base = doc->getRoot();
- NRArena *arena = NRArena::create();
+ Inkscape::Drawing drawing;
unsigned dkey = SPItem::display_key_new(1);
- NRArenaItem *root = base->invoke_show(arena, dkey, SP_ITEM_SHOW_DISPLAY);
+ base->invoke_show(drawing, dkey, SP_ITEM_SHOW_DISPLAY);
/* Create renderer and context */
renderer = new CairoRenderer();
@@ -76,9 +75,7 @@ png_render_document_to_file(SPDocument *doc, gchar const *filename)
}
renderer->destroyContext(ctx);
- /* Release arena */
base->invoke_hide(dkey);
- nr_object_unref((NRObject *) arena);
/* end */
delete renderer;
diff --git a/src/extension/internal/cairo-ps-out.cpp b/src/extension/internal/cairo-ps-out.cpp
index 7fdfaf8df..9cc3a4ce3 100644
--- a/src/extension/internal/cairo-ps-out.cpp
+++ b/src/extension/internal/cairo-ps-out.cpp
@@ -29,8 +29,7 @@
#include "extension/print.h"
#include "extension/db.h"
#include "extension/output.h"
-#include "display/nr-arena.h"
-#include "display/nr-arena-item.h"
+#include "display/drawing.h"
#include "display/curve.h"
#include "display/canvas-bpath.h"
@@ -86,10 +85,9 @@ ps_print_document_to_file(SPDocument *doc, gchar const *filename, unsigned int l
if (!base)
return false;
- /* Create new arena */
- NRArena *arena = NRArena::create();
+ Inkscape::Drawing drawing;
unsigned dkey = SPItem::display_key_new(1);
- base->invoke_show(arena, dkey, SP_ITEM_SHOW_DISPLAY);
+ base->invoke_show(drawing, dkey, SP_ITEM_SHOW_DISPLAY);
/* Create renderer and context */
CairoRenderer *renderer = new CairoRenderer();
@@ -111,9 +109,7 @@ ps_print_document_to_file(SPDocument *doc, gchar const *filename, unsigned int l
}
}
- /* Release arena */
base->invoke_hide(dkey);
- nr_object_unref((NRObject *) arena);
renderer->destroyContext(ctx);
delete renderer;
diff --git a/src/extension/internal/cairo-render-context.cpp b/src/extension/internal/cairo-render-context.cpp
index 22b68b0ca..c3a8a790b 100644
--- a/src/extension/internal/cairo-render-context.cpp
+++ b/src/extension/internal/cairo-render-context.cpp
@@ -32,9 +32,8 @@
#include <glib/gmem.h>
#include <glibmm/i18n.h>
-#include "display/nr-arena.h"
-#include "display/nr-arena-item.h"
-#include "display/nr-arena-group.h"
+#include "display/drawing.h"
+#include "display/display-forward.h"
#include "display/curve.h"
#include "display/canvas-bpath.h"
#include "display/cairo-utils.h"
@@ -91,14 +90,14 @@
struct SPClipPathView {
SPClipPathView *next;
unsigned int key;
- NRArenaItem *arenaitem;
+ Inkscape::DrawingItem *arenaitem;
NRRect bbox;
};
struct SPMaskView {
SPMaskView *next;
unsigned int key;
- NRArenaItem *arenaitem;
+ Inkscape::DrawingItem *arenaitem;
NRRect bbox;
};
@@ -1093,8 +1092,8 @@ CairoRenderContext::_createPatternPainter(SPPaintServer const *const paintserver
pattern_ctx->setTransform(&pcs2dev);
pattern_ctx->pushState();
- // create arena and group
- NRArena *arena = NRArena::create();
+ // create drawing and group
+ Inkscape::Drawing drawing;
unsigned dkey = SPItem::display_key_new(1);
// show items and render them
@@ -1102,7 +1101,7 @@ CairoRenderContext::_createPatternPainter(SPPaintServer const *const paintserver
if (pat_i && SP_IS_OBJECT (pat_i) && pattern_hasItemChildren(pat_i)) { // find the first one with item children
for ( SPObject *child = pat_i->firstChild() ; child; child = child->getNext() ) {
if (SP_IS_ITEM (child)) {
- SP_ITEM (child)->invoke_show (arena, dkey, SP_ITEM_REFERENCE_FLAGS);
+ SP_ITEM (child)->invoke_show (drawing, dkey, SP_ITEM_REFERENCE_FLAGS);
_renderer->renderItem(pattern_ctx, SP_ITEM (child));
}
}
diff --git a/src/extension/internal/cairo-renderer-pdf-out.cpp b/src/extension/internal/cairo-renderer-pdf-out.cpp
index 5d7c82bff..7ea5718f7 100644
--- a/src/extension/internal/cairo-renderer-pdf-out.cpp
+++ b/src/extension/internal/cairo-renderer-pdf-out.cpp
@@ -29,8 +29,7 @@
#include "extension/print.h"
#include "extension/db.h"
#include "extension/output.h"
-#include "display/nr-arena.h"
-#include "display/nr-arena-item.h"
+#include "display/drawing.h"
#include "display/curve.h"
#include "display/canvas-bpath.h"
@@ -82,10 +81,10 @@ pdf_render_document_to_file(SPDocument *doc, gchar const *filename, unsigned int
}
/* Create new arena */
- NRArena *arena = NRArena::create();
- nr_arena_set_renderoffscreen (arena);
+ Inkscape::Drawing drawing;
+ drawing.setExact(true);
unsigned dkey = SPItem::display_key_new(1);
- base->invoke_show(arena, dkey, SP_ITEM_SHOW_DISPLAY);
+ base->invoke_show(drawing, dkey, SP_ITEM_SHOW_DISPLAY);
/* Create renderer and context */
CairoRenderer *renderer = new CairoRenderer();
@@ -106,9 +105,7 @@ pdf_render_document_to_file(SPDocument *doc, gchar const *filename, unsigned int
}
}
- /* Release arena */
base->invoke_hide(dkey);
- nr_object_unref((NRObject *) arena);
renderer->destroyContext(ctx);
delete renderer;
diff --git a/src/extension/internal/cairo-renderer.cpp b/src/extension/internal/cairo-renderer.cpp
index 7eb7881dc..5e7fb991a 100644
--- a/src/extension/internal/cairo-renderer.cpp
+++ b/src/extension/internal/cairo-renderer.cpp
@@ -36,9 +36,7 @@
#include <glib/gmem.h>
#include <glibmm/i18n.h>
-#include "display/nr-arena.h"
-#include "display/nr-arena-item.h"
-#include "display/nr-arena-group.h"
+#include "display/display-forward.h"
#include "display/curve.h"
#include "display/canvas-bpath.h"
#include "display/cairo-utils.h"
@@ -88,14 +86,14 @@
struct SPClipPathView {
SPClipPathView *next;
unsigned int key;
- NRArenaItem *arenaitem;
+ Inkscape::DrawingItem *arenaitem;
NRRect bbox;
};
struct SPMaskView {
SPMaskView *next;
unsigned int key;
- NRArenaItem *arenaitem;
+ Inkscape::DrawingItem *arenaitem;
NRRect bbox;
};
diff --git a/src/extension/internal/emf-win32-inout.cpp b/src/extension/internal/emf-win32-inout.cpp
index e4997fce1..f1f0ef3cb 100644
--- a/src/extension/internal/emf-win32-inout.cpp
+++ b/src/extension/internal/emf-win32-inout.cpp
@@ -36,8 +36,8 @@
#include "extension/print.h"
#include "extension/db.h"
#include "extension/output.h"
-#include "display/nr-arena.h"
-#include "display/nr-arena-item.h"
+#include "display/drawing.h"
+#include "display/drawing-item.h"
#include "unit-constants.h"
#include "clear-n_.h"
@@ -106,9 +106,10 @@ emf_print_document_to_file(SPDocument *doc, gchar const *filename)
/* fixme: This has to go into module constructor somehow */
/* Create new arena */
mod->base = doc->getRoot();
- mod->arena = NRArena::create();
+ Inkscape::Drawing drawing;
mod->dkey = SPItem::display_key_new(1);
- mod->root = mod->base->invoke_show(mod->arena, mod->dkey, SP_ITEM_SHOW_DISPLAY);
+ mod->root = mod->base->invoke_show(drawing, mod->dkey, SP_ITEM_SHOW_DISPLAY);
+ drawing.setRoot(mod->root);
/* Print document */
ret = mod->begin(doc);
if (ret) {
@@ -120,9 +121,7 @@ emf_print_document_to_file(SPDocument *doc, gchar const *filename)
/* Release arena */
mod->base->invoke_hide(mod->dkey);
mod->base = NULL;
- mod->root = NULL;
- nr_object_unref((NRObject *) mod->arena);
- mod->arena = NULL;
+ mod->root = NULL; // deleted by invoke_hide
/* end */
mod->set_param_string("destination", oldoutput);
diff --git a/src/extension/internal/latex-pstricks-out.cpp b/src/extension/internal/latex-pstricks-out.cpp
index 376db7ee3..3a16268e6 100644
--- a/src/extension/internal/latex-pstricks-out.cpp
+++ b/src/extension/internal/latex-pstricks-out.cpp
@@ -18,8 +18,8 @@
#include "extension/system.h"
#include "extension/print.h"
#include "extension/db.h"
-#include "display/nr-arena.h"
-#include "display/nr-arena-item.h"
+#include "display/display-forward.h"
+#include "display/drawing.h"
#include "sp-root.h"
@@ -61,21 +61,19 @@ void LatexOutput::save(Inkscape::Extension::Output * /*mod2*/, SPDocument *doc,
/* Start */
context.module = mod;
/* fixme: This has to go into module constructor somehow */
- // Create new arena
mod->base = doc->getRoot();
- mod->arena = NRArena::create();
+ Inkscape::Drawing drawing;
mod->dkey = SPItem::display_key_new (1);
- mod->root = (mod->base)->invoke_show (mod->arena, mod->dkey, SP_ITEM_SHOW_DISPLAY);
+ mod->root = (mod->base)->invoke_show (drawing, mod->dkey, SP_ITEM_SHOW_DISPLAY);
+ drawing.setRoot(mod->root);
/* Print document */
ret = mod->begin (doc);
(mod->base)->invoke_print (&context);
ret = mod->finish ();
- /* Release arena */
+ /* Release things */
(mod->base)->invoke_hide (mod->dkey);
mod->base = NULL;
- mod->root = NULL;
- nr_object_unref ((NRObject *) mod->arena);
- mod->arena = NULL;
+ mod->root = NULL; // should have been deleted by invoke_hide
/* end */
mod->set_param_string("destination", oldoutput);
diff --git a/src/extension/print.cpp b/src/extension/print.cpp
index ad8c4c38d..f2dbb0b9b 100644
--- a/src/extension/print.cpp
+++ b/src/extension/print.cpp
@@ -15,25 +15,22 @@
namespace Inkscape {
namespace Extension {
-Print::Print (Inkscape::XML::Node * in_repr, Implementation::Implementation * in_imp) : Extension(in_repr, in_imp)
+Print::Print (Inkscape::XML::Node * in_repr, Implementation::Implementation * in_imp)
+ : Extension(in_repr, in_imp)
+ , base(NULL)
+ , drawing(NULL)
+ , root(NULL)
+ , dkey(0)
{
- base = NULL;
- arena = NULL;
- root = NULL;
- dkey = 0;
-
- return;
}
Print::~Print (void)
-{
- return;
-}
+{}
bool
Print::check (void)
{
- return Extension::check();
+ return Extension::check();
}
unsigned int
@@ -108,14 +105,14 @@ Print::text (const char* text, Geom::Point p, const SPStyle* style)
bool
Print::textToPath (void)
{
- return imp->textToPath(this);
+ return imp->textToPath(this);
}
//whether embed font in print output (EPS especially)
bool
Print::fontEmbedded (void)
{
- return imp->fontEmbedded(this);
+ return imp->fontEmbedded(this);
}
} } /* namespace Inkscape, Extension */
diff --git a/src/extension/print.h b/src/extension/print.h
index d5218aed8..c2276126b 100644
--- a/src/extension/print.h
+++ b/src/extension/print.h
@@ -13,7 +13,7 @@
#include "extension.h"
-#include "display/nr-arena-forward.h"
+#include "display/display-forward.h"
#include "forward.h"
#include "sp-item.h"
namespace Inkscape {
@@ -22,10 +22,10 @@ namespace Extension {
class Print : public Extension {
public: /* TODO: These are public for the short term, but this should be fixed */
- SPItem *base; /**< TODO: Document these */
- NRArena *arena; /**< TODO: Document these */
- NRArenaItem *root; /**< TODO: Document these */
- unsigned int dkey; /**< TODO: Document these */
+ SPItem *base;
+ Inkscape::Drawing *drawing;
+ Inkscape::DrawingItem *root;
+ unsigned int dkey;
public:
Print (Inkscape::XML::Node * in_repr,
diff --git a/src/flood-context.cpp b/src/flood-context.cpp
index 16a2e6ea7..8603f8b66 100644
--- a/src/flood-context.cpp
+++ b/src/flood-context.cpp
@@ -20,53 +20,52 @@
#include "config.h"
#endif
+#include <2geom/pathvector.h>
#include <gdk/gdkkeysyms.h>
#include <queue>
#include <deque>
+#include <glibmm/i18n.h>
-#include "macros.h"
-#include "display/sp-canvas.h"
-#include "document.h"
-#include "sp-namedview.h"
-#include "sp-object.h"
-#include "sp-rect.h"
-#include "selection.h"
-#include "desktop-handles.h"
+#include "color.h"
+#include "context-fns.h"
#include "desktop.h"
+#include "desktop-handles.h"
#include "desktop-style.h"
-#include "message-stack.h"
-#include "message-context.h"
-#include "pixmaps/cursor-paintbucket.xpm"
+#include "display/cairo-utils.h"
+#include "display/drawing-context.h"
+#include "display/drawing-image.h"
+#include "display/drawing-item.h"
+#include "display/drawing.h"
+#include "display/sp-canvas.h"
+#include "document.h"
#include "flood-context.h"
-#include "sp-metrics.h"
-#include <glibmm/i18n.h>
+#include "livarot/Path.h"
+#include "livarot/Shape.h"
+#include "macros.h"
+#include "message-context.h"
+#include "message-stack.h"
#include "object-edit.h"
-#include "xml/repr.h"
-#include "xml/node-event-vector.h"
#include "preferences.h"
-#include "context-fns.h"
#include "rubberband.h"
+#include "selection.h"
#include "shape-editor.h"
-
-#include "display/nr-arena-item.h"
-#include "display/nr-arena.h"
-#include "display/nr-arena-image.h"
-#include "display/canvas-arena.h"
-#include "display/cairo-utils.h"
-#include <2geom/pathvector.h>
-#include "sp-item.h"
-#include "sp-root.h"
#include "sp-defs.h"
-#include "sp-path.h"
+#include "sp-item.h"
#include "splivarot.h"
-#include "livarot/Path.h"
-#include "livarot/Shape.h"
+#include "sp-metrics.h"
+#include "sp-namedview.h"
+#include "sp-object.h"
+#include "sp-path.h"
+#include "sp-rect.h"
+#include "sp-root.h"
#include "svg/svg.h"
-#include "color.h"
-
-#include "trace/trace.h"
#include "trace/imagemap.h"
#include "trace/potrace/inkscape-potrace.h"
+#include "trace/trace.h"
+#include "xml/node-event-vector.h"
+#include "xml/repr.h"
+
+#include "pixmaps/cursor-paintbucket.xpm"
using Inkscape::DocumentUndo;
@@ -777,10 +776,6 @@ static void sp_flood_do_flood_fill(SPEventContext *event_context, GdkEvent *even
SPDesktop *desktop = event_context->desktop;
SPDocument *document = sp_desktop_document(desktop);
- /* Create new arena */
- NRArena *arena = NRArena::create();
- unsigned dkey = SPItem::display_key_new(1);
-
document->ensureUpToDate();
Geom::OptRect bbox = document->getRoot()->getBounds(Geom::identity());
@@ -804,56 +799,51 @@ static void sp_flood_do_flood_fill(SPEventContext *event_context, GdkEvent *even
Geom::Point origin(screen.min()[Geom::X],
document->getHeight() - screen.height() - screen.min()[Geom::Y]);
- origin[Geom::X] = origin[Geom::X] + (screen.width() * ((1 - padding) / 2));
- origin[Geom::Y] = origin[Geom::Y] + (screen.height() * ((1 - padding) / 2));
+ origin[Geom::X] += (screen.width() * ((1 - padding) / 2));
+ origin[Geom::Y] += (screen.height() * ((1 - padding) / 2));
Geom::Scale scale(zoom_scale, zoom_scale);
Geom::Affine affine = scale * Geom::Translate(-origin * scale);
-
- /* Create ArenaItems and set transform */
- NRArenaItem *root = document->getRoot()->invoke_show( arena, dkey, SP_ITEM_SHOW_DISPLAY);
- nr_arena_item_set_transform(NR_ARENA_ITEM(root), affine);
-
- NRGC gc(NULL);
- gc.transform.setIdentity();
-
- NRRectL final_bbox;
- final_bbox.x0 = 0;
- final_bbox.y0 = 0; //row;
- final_bbox.x1 = width;
- final_bbox.y1 = height; //row + num_rows;
-
- nr_arena_item_invoke_update(root, &final_bbox, &gc, NR_ARENA_ITEM_STATE_ALL, NR_ARENA_ITEM_STATE_NONE);
int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
guchar *px = g_new(guchar, stride * height);
-
- cairo_surface_t *s = cairo_image_surface_create_for_data(
- px, CAIRO_FORMAT_ARGB32, width, height, stride);
- cairo_t *ct = cairo_create(s);
- // cairo_translate not necessary here - surface origin is at 0,0
-
- SPNamedView *nv = sp_desktop_namedview(desktop);
- guint32 bgcolor = nv->pagecolor;
- // bgcolor is 0xrrggbbaa, we need 0xaarrggbb
- guint32 dtc = (bgcolor >> 8) | (bgcolor << 24);
-
- ink_cairo_set_source_rgba32(ct, bgcolor);
- cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE);
- cairo_paint(ct);
- cairo_set_operator(ct, CAIRO_OPERATOR_OVER);
-
- nr_arena_item_invoke_render(ct, root, &final_bbox, NULL, NR_ARENA_ITEM_RENDER_NO_CACHE );
-
- cairo_surface_flush(s);
- cairo_destroy(ct);
- cairo_surface_destroy(s);
-
- // Hide items
- document->getRoot()->invoke_hide(dkey);
+ guint32 bgcolor, dtc;
+
+ { // this block limits the lifetime of Drawing and DrawingContext
+ /* Create DrawingItems and set transform */
+ unsigned dkey = SPItem::display_key_new(1);
+ Inkscape::Drawing drawing;
+ Inkscape::DrawingItem *root = document->getRoot()->invoke_show( drawing, dkey, SP_ITEM_SHOW_DISPLAY);
+ root->setTransform(affine);
+ drawing.setRoot(root);
+
+ Geom::IntRect final_bbox = Geom::IntRect::from_xywh(0, 0, width, height);
+ drawing.update(final_bbox);
+
+ cairo_surface_t *s = cairo_image_surface_create_for_data(
+ px, CAIRO_FORMAT_ARGB32, width, height, stride);
+ Inkscape::DrawingContext ct(s, Geom::Point(0,0));
+ // cairo_translate not necessary here - surface origin is at 0,0
+
+ SPNamedView *nv = sp_desktop_namedview(desktop);
+ bgcolor = nv->pagecolor;
+ // bgcolor is 0xrrggbbaa, we need 0xaarrggbb
+ dtc = (bgcolor >> 8) | (bgcolor << 24);
+
+ ct.setSource(bgcolor);
+ ct.setOperator(CAIRO_OPERATOR_SOURCE);
+ ct.paint();
+ ct.setOperator(CAIRO_OPERATOR_OVER);
+
+ drawing.render(ct, final_bbox);
+
+ cairo_surface_flush(s);
+ cairo_surface_destroy(s);
+
+ // Hide items
+ document->getRoot()->invoke_hide(dkey);
+ }
- nr_object_unref((NRObject *) arena);
-
guchar *trace_px = g_new(guchar, width * height);
memset(trace_px, 0x00, width * height);
diff --git a/src/helper/Makefile_insert b/src/helper/Makefile_insert
index 2ccec8d16..7110c2025 100644
--- a/src/helper/Makefile_insert
+++ b/src/helper/Makefile_insert
@@ -18,7 +18,6 @@ ink_common_sources += \
helper/recthull.h \
helper/sp-marshal.cpp \
helper/sp-marshal.h \
- helper/stlport.h \
helper/unit-menu.cpp \
helper/unit-menu.h \
helper/unit-tracker.cpp \
diff --git a/src/helper/pixbuf-ops.cpp b/src/helper/pixbuf-ops.cpp
index 2e513afb2..3f987dc01 100644
--- a/src/helper/pixbuf-ops.cpp
+++ b/src/helper/pixbuf-ops.cpp
@@ -23,8 +23,9 @@
#include "interface.h"
#include "helper/png-write.h"
#include "display/cairo-utils.h"
-#include "display/nr-arena-item.h"
-#include "display/nr-arena.h"
+#include "display/drawing.h"
+#include "display/drawing-context.h"
+#include "display/drawing-item.h"
#include "document.h"
#include "sp-item.h"
#include "sp-root.h"
@@ -110,61 +111,48 @@ sp_generate_internal_bitmap(SPDocument *doc, gchar const */*filename*/,
{
if (width == 0 || height == 0) return NULL;
- GdkPixbuf* pixbuf = NULL;
- /* Create new arena for offscreen rendering*/
- NRArena *arena = NRArena::create();
- nr_arena_set_renderoffscreen(arena);
- unsigned dkey = SPItem::display_key_new(1);
+ GdkPixbuf* pixbuf = NULL;
+ /* Create new drawing for offscreen rendering*/
+ Inkscape::Drawing drawing;
+ drawing.setExact(true);
+ unsigned dkey = SPItem::display_key_new(1);
- doc->ensureUpToDate();
+ doc->ensureUpToDate();
- Geom::Rect screen=Geom::Rect(Geom::Point(x0,y0), Geom::Point(x1, y1));
+ Geom::Rect screen=Geom::Rect(Geom::Point(x0,y0), Geom::Point(x1, y1));
- double padding = 1.0;
+ double padding = 1.0;
- Geom::Point origin(screen.min()[Geom::X],
- doc->getHeight() - screen[Geom::Y].extent() - screen.min()[Geom::Y]);
+ Geom::Point origin(screen.min()[Geom::X],
+ doc->getHeight() - screen[Geom::Y].extent() - screen.min()[Geom::Y]);
- origin[Geom::X] = origin[Geom::X] + (screen[Geom::X].extent() * ((1 - padding) / 2));
- origin[Geom::Y] = origin[Geom::Y] + (screen[Geom::Y].extent() * ((1 - padding) / 2));
+ origin[Geom::X] = origin[Geom::X] + (screen[Geom::X].extent() * ((1 - padding) / 2));
+ origin[Geom::Y] = origin[Geom::Y] + (screen[Geom::Y].extent() * ((1 - padding) / 2));
- Geom::Scale scale( (xdpi / PX_PER_IN), (ydpi / PX_PER_IN));
- Geom::Affine affine = scale * Geom::Translate(-origin * scale);
+ Geom::Scale scale( (xdpi / PX_PER_IN), (ydpi / PX_PER_IN));
+ Geom::Affine affine = scale * Geom::Translate(-origin * scale);
- /* Create ArenaItems and set transform */
- NRArenaItem *root = doc->getRoot()->invoke_show( arena, dkey, SP_ITEM_SHOW_DISPLAY);
- nr_arena_item_set_transform(NR_ARENA_ITEM(root), affine);
+ /* Create ArenaItems and set transform */
+ Inkscape::DrawingItem *root = doc->getRoot()->invoke_show( drawing, dkey, SP_ITEM_SHOW_DISPLAY);
+ root->setTransform(affine);
+ drawing.setRoot(root);
- NRGC gc(NULL);
- gc.transform.setIdentity();
-
- // We show all and then hide all items we don't want, instead of showing only requested items,
- // because that would not work if the shown item references something in defs
- if (items_only) {
- hide_other_items_recursively(doc->getRoot(), items_only, dkey);
- }
-
- NRRectL final_bbox;
- final_bbox.x0 = 0;
- final_bbox.y0 = 0;//row;
- final_bbox.x1 = width;
- final_bbox.y1 = height;//row + num_rows;
+ // We show all and then hide all items we don't want, instead of showing only requested items,
+ // because that would not work if the shown item references something in defs
+ if (items_only) {
+ hide_other_items_recursively(doc->getRoot(), items_only, dkey);
+ }
- nr_arena_item_invoke_update(root, &final_bbox, &gc, NR_ARENA_ITEM_STATE_ALL, NR_ARENA_ITEM_STATE_NONE);
+ Geom::IntRect final_bbox = Geom::IntRect::from_xywh(0, 0, width, height);
+ drawing.update(final_bbox);
cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
if (cairo_surface_status(surface) == CAIRO_STATUS_SUCCESS) {
- cairo_t *ct = cairo_create(surface);
-
- // clear to background
- ink_cairo_set_source_rgba32(ct, bgcolor);
- cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE);
- cairo_paint(ct);
- cairo_set_operator(ct, CAIRO_OPERATOR_OVER);
+ Inkscape::DrawingContext ct(surface, Geom::Point(0,0));
// render items
- nr_arena_item_invoke_render(ct, root, &final_bbox, NULL, NR_ARENA_ITEM_RENDER_NO_CACHE );
+ drawing.render(ct, final_bbox, Inkscape::DrawingItem::RENDER_BYPASS_CACHE);
pixbuf = gdk_pixbuf_new_from_data(cairo_image_surface_get_data(surface),
GDK_COLORSPACE_RGB, TRUE,
@@ -179,8 +167,7 @@ sp_generate_internal_bitmap(SPDocument *doc, gchar const */*filename*/,
g_warning("sp_generate_internal_bitmap: not enough memory to create pixel buffer. Need %lld.", size);
cairo_surface_destroy(surface);
}
- doc->getRoot()->invoke_hide(dkey);
- nr_object_unref((NRObject *) arena);
+ doc->getRoot()->invoke_hide(dkey);
// gdk_pixbuf_save (pixbuf, "C:\\temp\\internal.jpg", "jpeg", NULL, "quality","100", NULL);
diff --git a/src/helper/png-write.cpp b/src/helper/png-write.cpp
index a23c8fd43..24da697c1 100644
--- a/src/helper/png-write.cpp
+++ b/src/helper/png-write.cpp
@@ -23,8 +23,9 @@
#include <png.h>
#include "png-write.h"
#include "io/sys.h"
-#include "display/nr-arena-item.h"
-#include "display/nr-arena.h"
+#include "display/drawing.h"
+#include "display/drawing-context.h"
+#include "display/drawing-item.h"
#include "document.h"
#include "sp-item.h"
#include "sp-root.h"
@@ -50,7 +51,7 @@ static unsigned int const MAX_STRIPE_SIZE = 1024*1024;
struct SPEBP {
unsigned long int width, height, sheight;
guint32 background;
- NRArenaItem *root; // the root arena item to show; it is assumed that all unneeded items are hidden
+ Inkscape::Drawing *drawing; // it is assumed that all unneeded items are hidden
guchar *px;
unsigned (*status)(float, void *);
void *data;
@@ -322,35 +323,24 @@ sp_export_get_rows(guchar const **rows, void **to_free, int row, int num_rows, v
// bbox is now set to the entire image to prevent discontinuities
// in the image when blur is used (the borders may still be a bit
// off, but that's less noticeable).
- NRRectL bbox;
- bbox.x0 = 0;
- bbox.y0 = row;
- bbox.x1 = ebp->width;
- bbox.y1 = row + num_rows;
- /* Update to renderable state */
- NRGC gc(NULL);
- gc.transform.setIdentity();
+ Geom::IntRect bbox = Geom::IntRect::from_xywh(0, row, ebp->width, num_rows);
- nr_arena_item_invoke_update(ebp->root, &bbox, &gc,
- NR_ARENA_ITEM_STATE_ALL, NR_ARENA_ITEM_STATE_NONE);
+ /* Update to renderable state */
+ ebp->drawing->update(bbox);
int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, ebp->width);
unsigned char *px = g_new(guchar, num_rows * stride);
cairo_surface_t *s = cairo_image_surface_create_for_data(
px, CAIRO_FORMAT_ARGB32, ebp->width, num_rows, stride);
- cairo_t *ct = cairo_create(s);
- cairo_translate(ct, -bbox.x0, -bbox.y0);
-
- ink_cairo_set_source_rgba32(ct, ebp->background);
- cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE);
- cairo_paint(ct);
- cairo_set_operator(ct, CAIRO_OPERATOR_OVER);
+ Inkscape::DrawingContext ct(s, bbox.min());
+ ct.setSource(ebp->background);
+ ct.setOperator(CAIRO_OPERATOR_SOURCE);
+ ct.paint();
+ ct.setOperator(CAIRO_OPERATOR_OVER);
/* Render */
- nr_arena_item_invoke_render(ct, ebp->root, &bbox, NULL, 0);
-
- cairo_destroy(ct);
+ ebp->drawing->render(ct, bbox);
cairo_surface_destroy(s);
*to_free = px;
@@ -460,15 +450,15 @@ sp_export_png_file(SPDocument *doc, gchar const *filename,
ebp.height = height;
ebp.background = bgcolor;
- /* Create new arena */
- NRArena *const arena = NRArena::create();
- // export with maximum blur rendering quality
- nr_arena_set_renderoffscreen(arena);
+ /* Create new drawing */
+ Inkscape::Drawing drawing;
+ drawing.setExact(true); // export with maximum blur rendering quality
unsigned const dkey = SPItem::display_key_new(1);
// Create ArenaItems and set transform
- ebp.root = doc->getRoot()->invoke_show(arena, dkey, SP_ITEM_SHOW_DISPLAY);
- nr_arena_item_set_transform(NR_ARENA_ITEM(ebp.root), affine);
+ drawing.setRoot(doc->getRoot()->invoke_show(drawing, dkey, SP_ITEM_SHOW_DISPLAY));
+ drawing.root()->setTransform(affine);
+ ebp.drawing = &drawing;
// We show all and then hide all items we don't want, instead of showing only requested items,
// because that would not work if the shown item references something in defs
@@ -492,9 +482,6 @@ sp_export_png_file(SPDocument *doc, gchar const *filename,
// Hide items, this releases arenaitem
doc->getRoot()->invoke_hide(dkey);
- /* Free arena */
- nr_object_unref((NRObject *) arena);
-
return write_status;
}
diff --git a/src/interface.cpp b/src/interface.cpp
index 25153097d..a981424fa 100644
--- a/src/interface.cpp
+++ b/src/interface.cpp
@@ -646,7 +646,7 @@ update_view_menu(GtkWidget *widget, GdkEventExpose */*event*/, gpointer user_dat
Inkscape::UI::View::View *view = (Inkscape::UI::View::View *) g_object_get_data(G_OBJECT(widget), "view");
SPDesktop *dt = static_cast<SPDesktop*>(view);
Inkscape::RenderMode mode = dt->getMode();
- Inkscape::ColorRenderMode colormode = dt->getColorMode();
+ Inkscape::ColorMode colormode = dt->getColorMode();
bool new_state = false;
if (!strcmp(action->id, "ViewModeNormal")) {
@@ -656,11 +656,11 @@ update_view_menu(GtkWidget *widget, GdkEventExpose */*event*/, gpointer user_dat
} else if (!strcmp(action->id, "ViewModeOutline")) {
new_state = mode == Inkscape::RENDERMODE_OUTLINE;
} else if (!strcmp(action->id, "ViewColorModeNormal")) {
- new_state = colormode == Inkscape::COLORRENDERMODE_NORMAL;
+ new_state = colormode == Inkscape::COLORMODE_NORMAL;
} else if (!strcmp(action->id, "ViewColorModeGrayscale")) {
- new_state = colormode == Inkscape::COLORRENDERMODE_GRAYSCALE;
+ new_state = colormode == Inkscape::COLORMODE_GRAYSCALE;
} else if (!strcmp(action->id, "ViewColorModePrintColorsPreview")) {
- new_state = colormode == Inkscape::COLORRENDERMODE_PRINT_COLORS_PREVIEW;
+ new_state = colormode == Inkscape::COLORMODE_PRINT_COLORS_PREVIEW;
} else {
g_warning("update_view_menu does not handle this verb");
}
diff --git a/src/libnrtype/Layout-TNG-Output.cpp b/src/libnrtype/Layout-TNG-Output.cpp
index 610f92582..a72fa0180 100644
--- a/src/libnrtype/Layout-TNG-Output.cpp
+++ b/src/libnrtype/Layout-TNG-Output.cpp
@@ -10,7 +10,7 @@
*/
#include <glib/gmem.h>
#include "Layout-TNG.h"
-#include "display/nr-arena-glyphs.h"
+#include "display/drawing-text.h"
#include "style.h"
#include "print.h"
#include "extension/print.h"
@@ -81,28 +81,27 @@ void Layout::_getGlyphTransformMatrix(int glyph_index, Geom::Affine *matrix) con
}
}
-void Layout::show(NRArenaGroup *in_arena, NRRect const *paintbox) const
+void Layout::show(DrawingGroup *in_arena, NRRect const *paintbox) const
{
int glyph_index = 0;
for (unsigned span_index = 0 ; span_index < _spans.size() ; span_index++) {
if (_input_stream[_spans[span_index].in_input_stream_item]->Type() != TEXT_SOURCE) continue;
InputStreamTextSource const *text_source = static_cast<InputStreamTextSource const *>(_input_stream[_spans[span_index].in_input_stream_item]);
- NRArenaGlyphsGroup *nr_group = NRArenaGlyphsGroup::create(in_arena->arena);
- nr_arena_item_add_child(in_arena, nr_group, NULL);
- nr_arena_item_unref(nr_group);
- nr_arena_glyphs_group_set_style(nr_group, text_source->style);
+ DrawingText *nr_text = new DrawingText(in_arena->drawing());
+ nr_text->setStyle(text_source->style);
+
while (glyph_index < (int)_glyphs.size() && _characters[_glyphs[glyph_index].in_character].in_span == span_index) {
if (_characters[_glyphs[glyph_index].in_character].in_glyph != -1) {
Geom::Affine glyph_matrix;
_getGlyphTransformMatrix(glyph_index, &glyph_matrix);
- nr_arena_glyphs_group_add_component(nr_group, _spans[span_index].font, _glyphs[glyph_index].glyph, glyph_matrix);
+ nr_text->addComponent(_spans[span_index].font, _glyphs[glyph_index].glyph, glyph_matrix);
}
glyph_index++;
}
- nr_arena_glyphs_group_set_paintbox(NR_ARENA_GLYPHS_GROUP(nr_group), paintbox);
+ nr_text->setPaintBox(paintbox ? paintbox->upgrade_2geom() : Geom::OptRect());
+ in_arena->prependChild(nr_text);
}
- nr_arena_item_request_update(NR_ARENA_ITEM(in_arena), NR_ARENA_ITEM_STATE_ALL, FALSE);
}
void Layout::getBoundingBox(NRRect *bounding_box, Geom::Affine const &transform, int start, int length) const
diff --git a/src/libnrtype/Layout-TNG.h b/src/libnrtype/Layout-TNG.h
index 6ab02c0e3..25f80e9e9 100644
--- a/src/libnrtype/Layout-TNG.h
+++ b/src/libnrtype/Layout-TNG.h
@@ -37,7 +37,6 @@ using Inkscape::Extension::Internal::CairoRenderContext;
class SPStyle;
class Shape;
-class NRArenaGroup;
class SPPrintContext;
class SVGLength;
class Path;
@@ -46,6 +45,8 @@ class font_instance;
typedef struct _PangoFontDescription PangoFontDescription;
namespace Inkscape {
+class DrawingGroup;
+
namespace Text {
/** \brief Generates the layout for either wrapped or non-wrapped text and stores the result
@@ -327,7 +328,7 @@ public:
\param in_arena The arena to add the glyphs group to
\param paintbox The current rendering tile
*/
- void show(NRArenaGroup *in_arena, NRRect const *paintbox) const;
+ void show(DrawingGroup *in_arena, NRRect const *paintbox) const;
/** Calculates the smallest rectangle completely enclosing all the
glyphs.
diff --git a/src/marker.cpp b/src/marker.cpp
index d3fa83ed6..c8fa9218d 100644
--- a/src/marker.cpp
+++ b/src/marker.cpp
@@ -21,7 +21,7 @@
#include <2geom/affine.h>
#include <2geom/transforms.h>
#include "svg/svg.h"
-#include "display/nr-arena-group.h"
+#include "display/drawing-group.h"
#include "xml/repr.h"
#include "attributes.h"
#include "marker.h"
@@ -31,7 +31,7 @@
struct SPMarkerView {
SPMarkerView *next;
unsigned int key;
- std::vector<NRArenaItem *> items;
+ std::vector<Inkscape::DrawingItem *> items;
};
static void sp_marker_class_init (SPMarkerClass *klass);
@@ -43,7 +43,7 @@ static void sp_marker_set (SPObject *object, unsigned int key, const gchar *valu
static void sp_marker_update (SPObject *object, SPCtx *ctx, guint flags);
static Inkscape::XML::Node *sp_marker_write (SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags);
-static NRArenaItem *sp_marker_private_show (SPItem *item, NRArena *arena, unsigned int key, unsigned int flags);
+static Inkscape::DrawingItem *sp_marker_private_show (SPItem *item, Inkscape::Drawing &drawing, unsigned int key, unsigned int flags);
static void sp_marker_private_hide (SPItem *item, unsigned int key);
static void sp_marker_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags);
static void sp_marker_print (SPItem *item, SPPrintContext *ctx);
@@ -168,7 +168,7 @@ sp_marker_release (SPObject *object)
marker = (SPMarker *) object;
while (marker->views) {
- /* Destroy all NRArenaitems etc. */
+ /* Destroy all DrawingItems etc. */
/* Parent class ::hide method */
((SPItemClass *) parent_class)->hide ((SPItem *) marker, marker->views->key);
sp_marker_view_remove (marker, marker->views, TRUE);
@@ -444,12 +444,12 @@ static void sp_marker_update(SPObject *object, SPCtx *ctx, guint flags)
((SPObjectClass *) (parent_class))->update (object, (SPCtx *) &rctx, flags);
}
- // As last step set additional transform of arena group
+ // As last step set additional transform of drawing group
for (SPMarkerView *v = marker->views; v != NULL; v = v->next) {
for (unsigned i = 0 ; i < v->items.size() ; i++) {
if (v->items[i]) {
- Geom::Affine tmp = marker->c2p;
- nr_arena_group_set_child_transform(NR_ARENA_GROUP(v->items[i]), &tmp);
+ Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->items[i]);
+ g->setChildTransform(marker->c2p);
}
}
}
@@ -522,8 +522,8 @@ sp_marker_write (SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::X
/**
* This routine is disabled to break propagation.
*/
-static NRArenaItem *
-sp_marker_private_show (SPItem */*item*/, NRArena */*arena*/, unsigned int /*key*/, unsigned int /*flags*/)
+static Inkscape::DrawingItem *
+sp_marker_private_show (SPItem */*item*/, Inkscape::Drawing &/*drawing*/, unsigned int /*key*/, unsigned int /*flags*/)
{
/* Break propagation */
return NULL;
@@ -560,14 +560,14 @@ sp_marker_print (SPItem */*item*/, SPPrintContext */*ctx*/)
/**
* Removes any SPMarkerViews that a marker has with a specific key.
- * Set up the NRArenaItem array's size in the specified SPMarker's SPMarkerView.
+ * Set up the DrawingItem array's size in the specified SPMarker's SPMarkerView.
* This is called from sp_shape_update() for shapes that have markers. It
* removes the old view of the marker and establishes a new one, registering
* it with the marker's list of views for future updates.
*
* \param marker Marker to create views in.
* \param key Key to give each SPMarkerView.
- * \param size Number of NRArenaItems to put in the SPMarkerView.
+ * \param size Number of DrawingItems to put in the SPMarkerView.
*/
void
sp_marker_show_dimension (SPMarker *marker, unsigned int key, unsigned int size)
@@ -599,10 +599,10 @@ sp_marker_show_dimension (SPMarker *marker, unsigned int key, unsigned int size)
/**
* Shows an instance of a marker. This is called during sp_shape_update_marker_view()
- * show and transform a child item in the arena for all views with the given key.
+ * show and transform a child item in the drawing for all views with the given key.
*/
-NRArenaItem *
-sp_marker_show_instance ( SPMarker *marker, NRArenaItem *parent,
+Inkscape::DrawingItem *
+sp_marker_show_instance ( SPMarker *marker, Inkscape::DrawingItem *parent,
unsigned int key, unsigned int pos,
Geom::Affine const &base, float linewidth)
{
@@ -621,14 +621,13 @@ sp_marker_show_instance ( SPMarker *marker, NRArenaItem *parent,
if (!v->items[pos]) {
/* Parent class ::show method */
v->items[pos] = ((SPItemClass *) parent_class)->show ((SPItem *) marker,
- parent->arena, key,
+ parent->drawing(), key,
SP_ITEM_REFERENCE_FLAGS);
if (v->items[pos]) {
/* fixme: Position (Lauris) */
- nr_arena_item_add_child (parent, v->items[pos], NULL);
- /* nr_arena_item_unref (v->items[pos]); */
- Geom::Affine tmp = marker->c2p;
- nr_arena_group_set_child_transform((NRArenaGroup *) v->items[pos], &tmp);
+ parent->prependChild(v->items[pos]);
+ Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->items[pos]);
+ if (g) g->setChildTransform(marker->c2p);
}
}
if (v->items[pos]) {
@@ -643,8 +642,7 @@ sp_marker_show_instance ( SPMarker *marker, NRArenaItem *parent,
if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) {
m = Geom::Scale(linewidth) * m;
}
-
- nr_arena_item_set_transform(v->items[pos], m);
+ v->items[pos]->setTransform(m);
}
return v->items[pos];
}
@@ -695,7 +693,7 @@ sp_marker_view_remove (SPMarker *marker, SPMarkerView *view, unsigned int destro
if (destroyitems) {
for (i = 0; i < view->items.size(); i++) {
/* We have to walk through the whole array because there may be hidden items */
- if (view->items[i]) nr_arena_item_unref (view->items[i]);
+ delete view->items[i];
}
}
view->items.clear();
diff --git a/src/marker.h b/src/marker.h
index 09461b3a1..eb907e2fb 100644
--- a/src/marker.h
+++ b/src/marker.h
@@ -85,7 +85,7 @@ protected:
};
void sp_marker_show_dimension (SPMarker *marker, unsigned int key, unsigned int size);
-NRArenaItem *sp_marker_show_instance (SPMarker *marker, NRArenaItem *parent,
+Inkscape::DrawingItem *sp_marker_show_instance (SPMarker *marker, Inkscape::DrawingItem *parent,
unsigned int key, unsigned int pos,
Geom::Affine const &base, float linewidth);
void sp_marker_hide (SPMarker *marker, unsigned int key);
diff --git a/src/preferences-skeleton.h b/src/preferences-skeleton.h
index 70ec0def4..70193bf96 100644
--- a/src/preferences-skeleton.h
+++ b/src/preferences-skeleton.h
@@ -231,6 +231,7 @@ static char const preferences_skeleton[] =
" </group>\n"
"\n"
" <group id=\"options\">\n"
+" <group id=\"renderingcache\" size=\"64\" />"
" <group id=\"useoldpdfexporter\" value=\"0\" />"
" <group id=\"highlightoriginal\" value=\"1\" />"
" <group id=\"relinkclonesonduplicate\" value=\"0\" />"
diff --git a/src/print.cpp b/src/print.cpp
index 1ee58a3e6..2eadf0fa9 100644
--- a/src/print.cpp
+++ b/src/print.cpp
@@ -15,6 +15,8 @@
# include "config.h"
#endif
+#include "display/drawing.h"
+#include "display/drawing-item.h"
#include "inkscape.h"
#include "desktop.h"
#include "sp-item.h"
@@ -80,9 +82,6 @@ unsigned int sp_print_text(SPPrintContext *ctx, char const *text, Geom::Point p,
return ctx->module->text(text, p, style);
}
-#include "display/nr-arena.h"
-#include "display/nr-arena-item.h"
-
/* UI */
void
@@ -92,19 +91,11 @@ sp_print_document(Gtk::Window& parentWindow, SPDocument *doc)
// Build arena
SPItem *base = doc->getRoot();
- NRArena *arena = NRArena::create();
- unsigned int dkey = SPItem::display_key_new(1);
- // TODO investigate why we are grabbing root and then ignoring it.
- NRArenaItem *root = base->invoke_show(arena, dkey, SP_ITEM_SHOW_DISPLAY);
// Run print dialog
Inkscape::UI::Dialog::Print printop(doc,base);
Gtk::PrintOperationResult res = printop.run(Gtk::PRINT_OPERATION_ACTION_PRINT_DIALOG, parentWindow);
(void)res; // TODO handle this
-
- // Release arena
- base->invoke_hide(dkey);
- nr_object_unref((NRObject *) arena);
}
void
@@ -126,21 +117,20 @@ sp_print_document_to_file(SPDocument *doc, gchar const *filename)
/* Start */
context.module = mod;
/* fixme: This has to go into module constructor somehow */
- /* Create new arena */
+ /* Create new drawing */
mod->base = doc->getRoot();
- mod->arena = NRArena::create();
+ Inkscape::Drawing drawing;
mod->dkey = SPItem::display_key_new(1);
- mod->root = (mod->base)->invoke_show(mod->arena, mod->dkey, SP_ITEM_SHOW_DISPLAY);
+ mod->root = (mod->base)->invoke_show(drawing, mod->dkey, SP_ITEM_SHOW_DISPLAY);
+ drawing.setRoot(mod->root);
/* Print document */
ret = mod->begin(doc);
(mod->base)->invoke_print(&context);
ret = mod->finish();
- /* Release arena */
+ /* Release drawing items */
(mod->base)->invoke_hide(mod->dkey);
mod->base = NULL;
- mod->root = NULL;
- nr_object_unref((NRObject *) mod->arena);
- mod->arena = NULL;
+ mod->root = NULL; // should be deleted by invoke_hide
/* end */
mod->set_param_string("destination", oldoutput);
diff --git a/src/print.h b/src/print.h
index caea6ae3a..6bdbe4b82 100644
--- a/src/print.h
+++ b/src/print.h
@@ -17,6 +17,7 @@
#include "forward.h"
#include "extension/extension-forward.h"
+struct NRRect;
struct SPPrintContext {
Inkscape::Extension::Print *module;
};
diff --git a/src/select-context.cpp b/src/select-context.cpp
index 1ce3ccd25..ca0ed2438 100644
--- a/src/select-context.cpp
+++ b/src/select-context.cpp
@@ -46,7 +46,7 @@
#include "seltrans.h"
#include "box3d.h"
#include "display/sp-canvas.h"
-#include "display/nr-arena-item.h"
+#include "display/drawing-item.h"
using Inkscape::DocumentUndo;
@@ -418,7 +418,7 @@ sp_select_context_cycle_through_items(SPSelectContext *sc, Inkscape::Selection *
if (!sc->cycling_cur_item)
return;
- NRArenaItem *arenaitem;
+ Inkscape::DrawingItem *arenaitem;
SPDesktop *desktop = SP_EVENT_CONTEXT(sc)->desktop;
SPItem *item = SP_ITEM(sc->cycling_cur_item->data);
@@ -426,7 +426,7 @@ sp_select_context_cycle_through_items(SPSelectContext *sc, Inkscape::Selection *
if (!g_list_find(sc->cycling_items_selected_before, item) && selection->includes(item))
selection->remove(item);
arenaitem = item->get_arenaitem(desktop->dkey);
- nr_arena_item_set_opacity (arenaitem, 0.3);
+ arenaitem->setOpacity(0.3);
// Find next item and activate it
GList *next;
@@ -442,7 +442,7 @@ sp_select_context_cycle_through_items(SPSelectContext *sc, Inkscape::Selection *
sc->cycling_cur_item = next;
item = SP_ITEM(sc->cycling_cur_item->data);
arenaitem = item->get_arenaitem(desktop->dkey);
- nr_arena_item_set_opacity (arenaitem, 1.0);
+ arenaitem->setOpacity(1.0);
if (shift_pressed)
selection->add(item);
@@ -796,10 +796,10 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event)
g_assert(sc->cycling_cur_item != NULL || sc->cycling_items == NULL);
} else {
// ... otherwise reset opacities for outdated items ...
- NRArenaItem *arenaitem;
+ Inkscape::DrawingItem *arenaitem;
for(GList *l = sc->cycling_items_cmp; l != NULL; l = l->next) {
arenaitem = SP_ITEM(l->data)->get_arenaitem(desktop->dkey);
- nr_arena_item_set_opacity (arenaitem, 1.0);
+ arenaitem->setOpacity(1.0);
//if (!shift_pressed && !g_list_find(sc->cycling_items_selected_before, SP_ITEM(l->data)) && selection->includes(SP_ITEM(l->data)))
if (!g_list_find(sc->cycling_items_selected_before, SP_ITEM(l->data)) && selection->includes(SP_ITEM(l->data)))
selection->remove(SP_ITEM(l->data));
@@ -818,7 +818,7 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event)
for(GList *l = sc->cycling_items; l != NULL; l = l->next) {
item = SP_ITEM(l->data);
arenaitem = item->get_arenaitem(desktop->dkey);
- nr_arena_item_set_opacity (arenaitem, 0.3);
+ arenaitem->setOpacity(0.3);
if (selection->includes(item)) {
// already selected items are stored separately, too
sc->cycling_items_selected_before = g_list_append(sc->cycling_items_selected_before, item);
@@ -1093,10 +1093,10 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event)
if (alt) { // TODO: Should we have a variable like is_cycling or is it harmless to run this piece of code each time?
// quit cycle-selection and reset opacities
SPSelectContext *sc = SP_SELECT_CONTEXT(event_context);
- NRArenaItem *arenaitem;
+ Inkscape::DrawingItem *arenaitem;
for (GList *l = sc->cycling_items; l != NULL; l = g_list_next(l)) {
arenaitem = SP_ITEM(l->data)->get_arenaitem(desktop->dkey);
- nr_arena_item_set_opacity (arenaitem, 1.0);
+ arenaitem->setOpacity(1.0);
}
g_list_free(sc->cycling_items);
g_list_free(sc->cycling_items_selected_before);
diff --git a/src/sp-clippath.cpp b/src/sp-clippath.cpp
index 48e466628..0b3320e59 100644
--- a/src/sp-clippath.cpp
+++ b/src/sp-clippath.cpp
@@ -15,8 +15,8 @@
#include <cstring>
#include <string>
-#include "display/nr-arena.h"
-#include "display/nr-arena-group.h"
+#include "display/drawing.h"
+#include "display/drawing-group.h"
#include "xml/repr.h"
#include "enums.h"
@@ -24,6 +24,7 @@
#include "document.h"
#include "document-private.h"
#include "sp-item.h"
+#include "style.h"
#include <2geom/transforms.h>
@@ -32,11 +33,11 @@
struct SPClipPathView {
SPClipPathView *next;
unsigned int key;
- NRArenaItem *arenaitem;
+ Inkscape::DrawingItem *arenaitem;
NRRect bbox;
};
-SPClipPathView *sp_clippath_view_new_prepend(SPClipPathView *list, unsigned int key, NRArenaItem *arenaitem);
+SPClipPathView *sp_clippath_view_new_prepend(SPClipPathView *list, unsigned int key, Inkscape::DrawingItem *arenaitem);
SPClipPathView *sp_clippath_view_list_remove(SPClipPathView *list, SPClipPathView *view);
SPObjectGroupClass * SPClipPathClass::static_parent_class = 0;
@@ -155,11 +156,11 @@ void SPClipPath::childAdded(SPObject *object, Inkscape::XML::Node *child, Inksca
if (SP_IS_ITEM(ochild)) {
SPClipPath *cp = SP_CLIPPATH(object);
for (SPClipPathView *v = cp->display; v != NULL; v = v->next) {
- NRArenaItem *ac = SP_ITEM(ochild)->invoke_show( NR_ARENA_ITEM_ARENA(v->arenaitem),
+ Inkscape::DrawingItem *ac = SP_ITEM(ochild)->invoke_show( v->arenaitem->drawing(),
v->key,
SP_ITEM_REFERENCE_FLAGS);
if (ac) {
- nr_arena_item_add_child(v->arenaitem, ac, NULL);
+ v->arenaitem->prependChild(ac);
}
}
}
@@ -191,13 +192,14 @@ void SPClipPath::update(SPObject *object, SPCtx *ctx, guint flags)
SPClipPath *cp = SP_CLIPPATH(object);
for (SPClipPathView *v = cp->display; v != NULL; v = v->next) {
+ Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem);
if (cp->clipPathUnits == SP_CONTENT_UNITS_OBJECTBOUNDINGBOX) {
Geom::Affine t(Geom::Scale(v->bbox.x1 - v->bbox.x0, v->bbox.y1 - v->bbox.y0));
t[4] = v->bbox.x0;
t[5] = v->bbox.y0;
- nr_arena_group_set_child_transform(NR_ARENA_GROUP(v->arenaitem), &t);
+ g->setChildTransform(t);
} else {
- nr_arena_group_set_child_transform(NR_ARENA_GROUP(v->arenaitem), NULL);
+ g->setChildTransform(Geom::identity());
}
}
}
@@ -240,20 +242,17 @@ Inkscape::XML::Node *SPClipPath::write(SPObject *object, Inkscape::XML::Document
return repr;
}
-NRArenaItem *SPClipPath::show(NRArena *arena, unsigned int key)
+Inkscape::DrawingItem *SPClipPath::show(Inkscape::Drawing &drawing, unsigned int key)
{
- g_return_val_if_fail(arena != NULL, NULL);
- g_return_val_if_fail(NR_IS_ARENA(arena), NULL);
-
- NRArenaItem *ai = NRArenaGroup::create(arena);
+ Inkscape::DrawingGroup *ai = new Inkscape::DrawingGroup(drawing);
display = sp_clippath_view_new_prepend(display, key, ai);
for ( SPObject *child = firstChild() ; child ; child = child->getNext() ) {
if (SP_IS_ITEM(child)) {
- NRArenaItem *ac = SP_ITEM(child)->invoke_show(arena, key, SP_ITEM_REFERENCE_FLAGS);
+ Inkscape::DrawingItem *ac = SP_ITEM(child)->invoke_show(drawing, key, SP_ITEM_REFERENCE_FLAGS);
if (ac) {
/* The order is not important in clippath */
- nr_arena_item_add_child(ai, ac, NULL);
+ ai->appendChild(ac);
}
}
}
@@ -262,9 +261,9 @@ NRArenaItem *SPClipPath::show(NRArena *arena, unsigned int key)
Geom::Affine t(Geom::Scale(display->bbox.x1 - display->bbox.x0, display->bbox.y1 - display->bbox.y0));
t[4] = display->bbox.x0;
t[5] = display->bbox.y0;
- nr_arena_group_set_child_transform(NR_ARENA_GROUP(ai), &t);
+ ai->setChildTransform(t);
}
- nr_arena_group_set_style(NR_ARENA_GROUP(ai), this->style);
+ ai->setStyle(this->style);
return ai;
}
@@ -329,13 +328,13 @@ void SPClipPath::getBBox(NRRect *bbox, Geom::Affine const &transform, unsigned c
/* ClipPath views */
SPClipPathView *
-sp_clippath_view_new_prepend(SPClipPathView *list, unsigned int key, NRArenaItem *arenaitem)
+sp_clippath_view_new_prepend(SPClipPathView *list, unsigned int key, Inkscape::DrawingItem *arenaitem)
{
SPClipPathView *new_path_view = g_new(SPClipPathView, 1);
new_path_view->next = list;
new_path_view->key = key;
- new_path_view->arenaitem = nr_arena_item_ref(arenaitem);
+ new_path_view->arenaitem = arenaitem;
new_path_view->bbox.x0 = new_path_view->bbox.x1 = 0.0;
new_path_view->bbox.y0 = new_path_view->bbox.y1 = 0.0;
@@ -354,7 +353,7 @@ sp_clippath_view_list_remove(SPClipPathView *list, SPClipPathView *view)
prev->next = view->next;
}
- nr_arena_item_unref(view->arenaitem);
+ delete view->arenaitem;
g_free(view);
return list;
diff --git a/src/sp-clippath.h b/src/sp-clippath.h
index d3c650ca6..11817eb77 100644
--- a/src/sp-clippath.h
+++ b/src/sp-clippath.h
@@ -23,7 +23,7 @@
class SPClipPathView;
-#include "display/nr-arena-forward.h"
+#include "display/display-forward.h"
#include "libnr/nr-forward.h"
#include "sp-object-group.h"
#include "uri-references.h"
@@ -40,7 +40,7 @@ public:
static const gchar *create(GSList *reprs, SPDocument *document, Geom::Affine const* applyTransform);
static GType sp_clippath_get_type(void);
- NRArenaItem *show(NRArena *arena, unsigned int key);
+ Inkscape::DrawingItem *show(Inkscape::Drawing &drawing, unsigned int key);
void hide(unsigned int key);
void setBBox(unsigned int key, NRRect *bbox);
diff --git a/src/sp-flowtext.cpp b/src/sp-flowtext.cpp
index bb931a869..ea8079bba 100644
--- a/src/sp-flowtext.cpp
+++ b/src/sp-flowtext.cpp
@@ -31,7 +31,7 @@
#include "livarot/Shape.h"
-#include "display/nr-arena-glyphs.h"
+#include "display/drawing-text.h"
static void sp_flowtext_class_init(SPFlowtextClass *klass);
@@ -50,7 +50,7 @@ static void sp_flowtext_bbox(SPItem const *item, NRRect *bbox, Geom::Affine cons
static void sp_flowtext_print(SPItem *item, SPPrintContext *ctx);
static gchar *sp_flowtext_description(SPItem *item);
static void sp_flowtext_snappoints(SPItem const *item, std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs);
-static NRArenaItem *sp_flowtext_show(SPItem *item, NRArena *arena, unsigned key, unsigned flags);
+static Inkscape::DrawingItem *sp_flowtext_show(SPItem *item, Inkscape::Drawing &drawing, unsigned key, unsigned flags);
static void sp_flowtext_hide(SPItem *item, unsigned key);
static SPItemClass *parent_class;
@@ -179,10 +179,11 @@ static void sp_flowtext_update(SPObject *object, SPCtx *ctx, unsigned flags)
NRRect paintbox;
group->invoke_bbox( &paintbox, Geom::identity(), TRUE);
for (SPItemView *v = group->display; v != NULL; v = v->next) {
- group->_clearFlow(NR_ARENA_GROUP(v->arenaitem));
- nr_arena_group_set_style(NR_ARENA_GROUP(v->arenaitem), object->style);
+ Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem);
+ group->_clearFlow(g);
+ g->setStyle(object->style);
// pass the bbox of the flowtext object as paintbox (used for paintserver fills)
- group->layout.show(NR_ARENA_GROUP(v->arenaitem), &paintbox);
+ group->layout.show(g, &paintbox);
}
}
@@ -200,9 +201,10 @@ static void sp_flowtext_modified(SPObject *object, guint flags)
NRRect paintbox;
text->invoke_bbox( &paintbox, Geom::identity(), TRUE);
for (SPItemView* v = text->display; v != NULL; v = v->next) {
- text->_clearFlow(NR_ARENA_GROUP(v->arenaitem));
- nr_arena_group_set_style(NR_ARENA_GROUP(v->arenaitem), object->style);
- text->layout.show(NR_ARENA_GROUP(v->arenaitem), &paintbox);
+ Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem);
+ text->_clearFlow(g);
+ g->setStyle(object->style);
+ text->layout.show(g, &paintbox);
}
}
@@ -406,14 +408,13 @@ static void sp_flowtext_snappoints(SPItem const *item, std::vector<Inkscape::Sna
}
}
-static NRArenaItem *
-sp_flowtext_show(SPItem *item, NRArena *arena, unsigned/* key*/, unsigned /*flags*/)
+static Inkscape::DrawingItem *
+sp_flowtext_show(SPItem *item, Inkscape::Drawing &drawing, unsigned/* key*/, unsigned /*flags*/)
{
SPFlowtext *group = (SPFlowtext *) item;
- NRArenaGroup *flowed = NRArenaGroup::create(arena);
- nr_arena_group_set_transparent(flowed, FALSE);
-
- nr_arena_group_set_style(flowed, group->style);
+ Inkscape::DrawingGroup *flowed = new Inkscape::DrawingGroup(drawing);
+ flowed->setPickChildren(false);
+ flowed->setStyle(group->style);
// pass the bbox of the flowtext object as paintbox (used for paintserver fills)
NRRect paintbox;
@@ -541,17 +542,9 @@ void SPFlowtext::rebuildLayout()
//g_print(layout.dumpAsText().c_str());
}
-void SPFlowtext::_clearFlow(NRArenaGroup *in_arena)
+void SPFlowtext::_clearFlow(Inkscape::DrawingGroup *in_arena)
{
- nr_arena_item_request_render(NR_ARENA_ITEM(in_arena));
- for (NRArenaItem *child = in_arena->children; child != NULL; ) {
- NRArenaItem *nchild = child->next;
-
- nr_arena_glyphs_group_clear(NR_ARENA_GLYPHS_GROUP(child));
- nr_arena_item_remove_child(NR_ARENA_ITEM(in_arena), child);
-
- child = nchild;
- }
+ in_arena->clearChildren();
}
Inkscape::XML::Node *SPFlowtext::getAsText()
diff --git a/src/sp-flowtext.h b/src/sp-flowtext.h
index 3b0ce178a..de41ba47f 100644
--- a/src/sp-flowtext.h
+++ b/src/sp-flowtext.h
@@ -6,7 +6,7 @@
#include "sp-item.h"
-#include "display/nr-arena-forward.h"
+#include "display/display-forward.h"
#include <2geom/forward.h>
#include "libnrtype/Layout-TNG.h"
@@ -31,8 +31,8 @@ struct SPFlowtext : public SPItem {
//semiprivate: (need to be accessed by the C-style functions still)
Inkscape::Text::Layout layout;
- /** discards the NRArena objects representing this text. */
- void _clearFlow(NRArenaGroup* in_arena);
+ /** discards the drawing objects representing this text. */
+ void _clearFlow(Inkscape::DrawingGroup* in_arena);
double par_indent;
diff --git a/src/sp-image.cpp b/src/sp-image.cpp
index ea7d5089e..5f398b10e 100644
--- a/src/sp-image.cpp
+++ b/src/sp-image.cpp
@@ -28,7 +28,7 @@
#include <2geom/transforms.h>
#include <glibmm/i18n.h>
-#include "display/nr-arena-image.h"
+#include "display/drawing-image.h"
#include "display/cairo-utils.h"
#include "display/curve.h"
//Added for preserveAspectRatio support -- EAF
@@ -84,14 +84,14 @@ static void sp_image_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &
static void sp_image_print (SPItem * item, SPPrintContext *ctx);
static gchar * sp_image_description (SPItem * item);
static void sp_image_snappoints(SPItem const *item, std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs);
-static NRArenaItem *sp_image_show (SPItem *item, NRArena *arena, unsigned int key, unsigned int flags);
+static Inkscape::DrawingItem *sp_image_show (SPItem *item, Inkscape::Drawing &drawing, unsigned int key, unsigned int flags);
static Geom::Affine sp_image_set_transform (SPItem *item, Geom::Affine const &xform);
static void sp_image_set_curve(SPImage *image);
static GdkPixbuf *sp_image_repr_read_image( time_t& modTime, gchar*& pixPath, const gchar *href, const gchar *absref, const gchar *base );
static GdkPixbuf *sp_image_pixbuf_force_rgba (GdkPixbuf * pixbuf);
-static void sp_image_update_arenaitem (SPImage *img, NRArenaImage *ai);
+static void sp_image_update_arenaitem (SPImage *img, Inkscape::DrawingImage *ai);
static void sp_image_update_canvas_image (SPImage *image);
static GdkPixbuf * sp_image_repr_read_dataURI (const gchar * uri_data);
static GdkPixbuf * sp_image_repr_read_b64 (const gchar * uri_data);
@@ -1018,7 +1018,8 @@ static void sp_image_modified( SPObject *object, unsigned int flags )
if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) {
for (SPItemView *v = image->display; v != NULL; v = v->next) {
- nr_arena_image_set_style (NR_ARENA_IMAGE (v->arenaitem), object->style);
+ Inkscape::DrawingImage *img = dynamic_cast<Inkscape::DrawingImage *>(v->arenaitem);
+ img->setStyle(object->style);
}
}
}
@@ -1148,12 +1149,12 @@ static gchar *sp_image_description( SPItem *item )
return ret;
}
-static NRArenaItem *sp_image_show( SPItem *item, NRArena *arena, unsigned int /*key*/, unsigned int /*flags*/ )
+static Inkscape::DrawingItem *sp_image_show( SPItem *item, Inkscape::Drawing &drawing, unsigned int /*key*/, unsigned int /*flags*/ )
{
SPImage * image = SP_IMAGE(item);
- NRArenaItem *ai = NRArenaImage::create(arena);
+ Inkscape::DrawingImage *ai = new Inkscape::DrawingImage(drawing);
- sp_image_update_arenaitem(image, NR_ARENA_IMAGE(ai));
+ sp_image_update_arenaitem(image, ai);
return ai;
}
@@ -1264,13 +1265,13 @@ static GdkPixbuf *sp_image_pixbuf_force_rgba( GdkPixbuf * pixbuf )
/* We assert that realpixbuf is either NULL or identical size to pixbuf */
static void
-sp_image_update_arenaitem (SPImage *image, NRArenaImage *ai)
+sp_image_update_arenaitem (SPImage *image, Inkscape::DrawingImage *ai)
{
- nr_arena_image_set_style(ai, SP_OBJECT(image)->style);
- nr_arena_image_set_argb32_pixbuf(ai, image->pixbuf);
- nr_arena_image_set_origin(ai, Geom::Point(image->ox, image->oy));
- nr_arena_image_set_scale(ai, image->sx, image->sy);
- nr_arena_image_set_clipbox(ai, image->clipbox);
+ ai->setStyle(SP_OBJECT(image)->style);
+ ai->setARGB32Pixbuf(image->pixbuf);
+ ai->setOrigin(Geom::Point(image->ox, image->oy));
+ ai->setScale(image->sx, image->sy);
+ ai->setClipbox(image->clipbox);
}
static void sp_image_update_canvas_image(SPImage *image)
@@ -1278,7 +1279,7 @@ static void sp_image_update_canvas_image(SPImage *image)
SPItem *item = SP_ITEM(image);
for (SPItemView *v = item->display; v != NULL; v = v->next) {
- sp_image_update_arenaitem(image, NR_ARENA_IMAGE(v->arenaitem));
+ sp_image_update_arenaitem(image, dynamic_cast<Inkscape::DrawingImage *>(v->arenaitem));
}
}
diff --git a/src/sp-item-group.cpp b/src/sp-item-group.cpp
index 491b2a62a..f8ab0460a 100644
--- a/src/sp-item-group.cpp
+++ b/src/sp-item-group.cpp
@@ -22,7 +22,7 @@
#include <cstring>
#include <string>
-#include "display/nr-arena-group.h"
+#include "display/drawing-group.h"
#include "display/curve.h"
#include "xml/repr.h"
#include "svg/svg.h"
@@ -68,7 +68,7 @@ static void sp_group_set(SPObject *object, unsigned key, char const *value);
static void sp_group_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags);
static void sp_group_print (SPItem * item, SPPrintContext *ctx);
static gchar * sp_group_description (SPItem * item);
-static NRArenaItem *sp_group_show (SPItem *item, NRArena *arena, unsigned int key, unsigned int flags);
+static Inkscape::DrawingItem *sp_group_show (SPItem *item, Inkscape::Drawing &drawing, unsigned int key, unsigned int flags);
static void sp_group_hide (SPItem * item, unsigned int key);
static void sp_group_snappoints (SPItem const *item, std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs);
@@ -312,10 +312,10 @@ static void sp_group_set(SPObject *object, unsigned key, char const *value) {
}
}
-static NRArenaItem *
-sp_group_show (SPItem *item, NRArena *arena, unsigned int key, unsigned int flags)
+static Inkscape::DrawingItem *
+sp_group_show (SPItem *item, Inkscape::Drawing &drawing, unsigned int key, unsigned int flags)
{
- return SP_GROUP(item)->group->show(arena, key, flags);
+ return SP_GROUP(item)->group->show(drawing, key, flags);
}
static void
@@ -562,9 +562,9 @@ void SPGroup::_updateLayerMode(unsigned int display_key) {
SPItemView *view;
for ( view = this->display ; view ; view = view->next ) {
if ( !display_key || view->key == display_key ) {
- NRArenaGroup *arena_group=NR_ARENA_GROUP(view->arenaitem);
- if (arena_group) {
- nr_arena_group_set_transparent(arena_group, effectiveLayerMode(view->key) == SPGroup::LAYER);
+ Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(view->arenaitem);
+ if (g) {
+ g->setPickChildren(effectiveLayerMode(view->key) == SPGroup::LAYER);
}
}
}
@@ -596,13 +596,13 @@ void CGroup::onChildAdded(Inkscape::XML::Node *child) {
if ( SP_IS_ITEM(ochild) ) {
/* TODO: this should be moved into SPItem somehow */
SPItemView *v;
- NRArenaItem *ac;
+ Inkscape::DrawingItem *ac;
for (v = _group->display; v != NULL; v = v->next) {
- ac = SP_ITEM (ochild)->invoke_show (NR_ARENA_ITEM_ARENA (v->arenaitem), v->key, v->flags);
+ ac = SP_ITEM (ochild)->invoke_show (v->arenaitem->drawing(), v->key, v->flags);
if (ac) {
- nr_arena_item_append_child (v->arenaitem, ac);
+ v->arenaitem->appendChild(ac);
}
}
}
@@ -611,16 +611,16 @@ void CGroup::onChildAdded(Inkscape::XML::Node *child) {
if ( ochild && SP_IS_ITEM(ochild) ) {
/* TODO: this should be moved into SPItem somehow */
SPItemView *v;
- NRArenaItem *ac;
+ Inkscape::DrawingItem *ac;
unsigned position = SP_ITEM(ochild)->pos_in_parent();
for (v = _group->display; v != NULL; v = v->next) {
- ac = SP_ITEM (ochild)->invoke_show (NR_ARENA_ITEM_ARENA (v->arenaitem), v->key, v->flags);
+ ac = SP_ITEM (ochild)->invoke_show (v->arenaitem->drawing(), v->key, v->flags);
if (ac) {
- nr_arena_item_add_child (v->arenaitem, ac, NULL);
- nr_arena_item_set_order (ac, position);
+ v->arenaitem->prependChild(ac);
+ ac->setZOrder(position);
}
}
}
@@ -646,10 +646,11 @@ void CGroup::onUpdate(SPCtx *ctx, unsigned int flags) {
flags &= SP_OBJECT_MODIFIED_CASCADE;
if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) {
- SPObject *object = _group;
- for (SPItemView *v = _group->display; v != NULL; v = v->next) {
- nr_arena_group_set_style(NR_ARENA_GROUP(v->arenaitem), object->style);
- }
+ SPObject *object = _group;
+ for (SPItemView *v = _group->display; v != NULL; v = v->next) {
+ Inkscape::DrawingGroup *group = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem);
+ group->setStyle(object->style);
+ }
}
GSList *l = g_slist_reverse(_group->childList(true, SPObject::ActionUpdate));
@@ -677,10 +678,11 @@ void CGroup::onModified(guint flags) {
flags &= SP_OBJECT_MODIFIED_CASCADE;
if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) {
- SPObject *object = _group;
- for (SPItemView *v = _group->display; v != NULL; v = v->next) {
- nr_arena_group_set_style(NR_ARENA_GROUP(v->arenaitem), object->style);
- }
+ SPObject *object = _group;
+ for (SPItemView *v = _group->display; v != NULL; v = v->next) {
+ Inkscape::DrawingGroup *group = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem);
+ group->setStyle(object->style);
+ }
}
GSList *l = g_slist_reverse(_group->childList(true));
@@ -742,35 +744,28 @@ gchar *CGroup::getDescription() {
len), len);
}
-NRArenaItem *CGroup::show (NRArena *arena, unsigned int key, unsigned int flags) {
- NRArenaItem *ai;
+Inkscape::DrawingItem *CGroup::show (Inkscape::Drawing &drawing, unsigned int key, unsigned int flags) {
+ Inkscape::DrawingGroup *ai;
SPObject *object = _group;
- ai = NRArenaGroup::create(arena);
+ ai = new Inkscape::DrawingGroup(drawing);
+ ai->setPickChildren(_group->effectiveLayerMode(key) == SPGroup::LAYER);
+ ai->setStyle(object->style);
- nr_arena_group_set_transparent(NR_ARENA_GROUP (ai),
- _group->effectiveLayerMode(key) ==
- SPGroup::LAYER);
- nr_arena_group_set_style(NR_ARENA_GROUP(ai), object->style);
-
- _showChildren(arena, ai, key, flags);
+ _showChildren(drawing, ai, key, flags);
return ai;
}
-void CGroup::_showChildren (NRArena *arena, NRArenaItem *ai, unsigned int key, unsigned int flags) {
- NRArenaItem *ac = NULL;
- NRArenaItem *ar = NULL;
+void CGroup::_showChildren (Inkscape::Drawing &drawing, Inkscape::DrawingItem *ai, unsigned int key, unsigned int flags) {
+ Inkscape::DrawingItem *ac = NULL;
SPItem * child = NULL;
GSList *l = g_slist_reverse(_group->childList(false, SPObject::ActionShow));
while (l) {
SPObject *o = SP_OBJECT (l->data);
if (SP_IS_ITEM (o)) {
child = SP_ITEM (o);
- ac = child->invoke_show (arena, key, flags);
- if (ac) {
- nr_arena_item_add_child (ai, ac, ar);
- ar = ac;
- }
+ ac = child->invoke_show (drawing, key, flags);
+ ai->appendChild(ac);
}
l = g_slist_remove (l, o);
}
@@ -801,7 +796,7 @@ void CGroup::onOrderChanged (Inkscape::XML::Node *child, Inkscape::XML::Node *,
SPItemView *v;
unsigned position = SP_ITEM(ochild)->pos_in_parent();
for ( v = SP_ITEM (ochild)->display ; v != NULL ; v = v->next ) {
- nr_arena_item_set_order (v->arenaitem, position);
+ v->arenaitem->setZOrder(position);
}
}
diff --git a/src/sp-item-group.h b/src/sp-item-group.h
index e2aeb8bc5..99f375e44 100644
--- a/src/sp-item-group.h
+++ b/src/sp-item-group.h
@@ -73,13 +73,13 @@ public:
virtual void onPrint(SPPrintContext *ctx);
virtual void onOrderChanged(Inkscape::XML::Node *child, Inkscape::XML::Node *old_ref, Inkscape::XML::Node *new_ref);
virtual gchar *getDescription();
- virtual NRArenaItem *show (NRArena *arena, unsigned int key, unsigned int flags);
+ virtual Inkscape::DrawingItem *show (Inkscape::Drawing &drawing, unsigned int key, unsigned int flags);
virtual void hide (unsigned int key);
gint getItemCount();
protected:
- virtual void _showChildren (NRArena *arena, NRArenaItem *ai, unsigned int key, unsigned int flags);
+ virtual void _showChildren (Inkscape::Drawing &drawing, Inkscape::DrawingItem *ai, unsigned int key, unsigned int flags);
SPGroup *_group;
};
diff --git a/src/sp-item.cpp b/src/sp-item.cpp
index a4f2efa2c..07ce73c4b 100644
--- a/src/sp-item.cpp
+++ b/src/sp-item.cpp
@@ -29,8 +29,7 @@
#include "sp-item.h"
#include "svg/svg.h"
#include "print.h"
-#include "display/nr-arena.h"
-#include "display/nr-arena-item.h"
+#include "display/drawing-item.h"
#include "attributes.h"
#include "document.h"
#include "uri.h"
@@ -145,14 +144,10 @@ void SPItem::init() {
display = NULL;
clip_ref = new SPClipPathReference(this);
- sigc::signal<void, SPObject *, SPObject *> cs1 = clip_ref->changedSignal();
- sigc::slot2<void,SPObject*, SPObject *> sl1 = sigc::bind(sigc::ptr_fun(clip_ref_changed), this);
- _clip_ref_connection = cs1.connect(sl1);
+ clip_ref->changedSignal().connect(sigc::bind(sigc::ptr_fun(clip_ref_changed), this));
mask_ref = new SPMaskReference(this);
- sigc::signal<void, SPObject *, SPObject *> cs2 = mask_ref->changedSignal();
- sigc::slot2<void,SPObject*, SPObject *> sl2=sigc::bind(sigc::ptr_fun(mask_ref_changed), this);
- _mask_ref_connection = cs2.connect(sl2);
+ mask_ref->changedSignal().connect(sigc::bind(sigc::ptr_fun(mask_ref_changed), this));
avoidRef = new SPAvoidRef(this);
@@ -204,10 +199,10 @@ bool SPItem::isHidden(unsigned display_key) const {
for ( SPItemView *view(display) ; view ; view = view->next ) {
if ( view->key == display_key ) {
g_assert(view->arenaitem != NULL);
- for ( NRArenaItem *arenaitem = view->arenaitem ;
- arenaitem ; arenaitem = arenaitem->parent )
+ for ( Inkscape::DrawingItem *arenaitem = view->arenaitem ;
+ arenaitem ; arenaitem = arenaitem->parent() )
{
- if (!arenaitem->visible) {
+ if (!arenaitem->visible()) {
return true;
}
}
@@ -394,35 +389,22 @@ void SPItem::sp_item_release(SPObject *object)
{
SPItem *item = (SPItem *) object;
- item->_clip_ref_connection.disconnect();
- item->_mask_ref_connection.disconnect();
-
// Note: do this here before the clip_ref is deleted, since calling
// ensureUpToDate() for triggered routing may reference
// the deleted clip_ref.
- if (item->avoidRef) {
- delete item->avoidRef;
- item->avoidRef = NULL;
- }
+ delete item->avoidRef;
- if (item->clip_ref) {
- item->clip_ref->detach();
- delete item->clip_ref;
- item->clip_ref = NULL;
- }
-
- if (item->mask_ref) {
- item->mask_ref->detach();
- delete item->mask_ref;
- item->mask_ref = NULL;
- }
+ // we do NOT disconnect from the changed signal of those before deletion.
+ // The destructor will call *_ref_changed with NULL as the new value,
+ // which will cause the hide() function to be called.
+ delete item->clip_ref;
+ delete item->mask_ref;
if (((SPObjectClass *) (SPItemClass::static_parent_class))->release) {
((SPObjectClass *) SPItemClass::static_parent_class)->release(object);
}
while (item->display) {
- nr_arena_item_unparent(item->display->arenaitem);
item->display = sp_item_view_list_remove(item->display, item->display);
}
@@ -478,7 +460,7 @@ void SPItem::sp_item_set(SPObject *object, unsigned key, gchar const *value)
case SP_ATTR_SODIPODI_INSENSITIVE:
item->sensitive = !value;
for (SPItemView *v = item->display; v != NULL; v = v->next) {
- nr_arena_item_set_sensitive(v->arenaitem, item->sensitive);
+ v->arenaitem->setSensitive(item->sensitive);
}
break;
case SP_ATTR_CONNECTOR_AVOID:
@@ -529,23 +511,21 @@ void SPItem::clip_ref_changed(SPObject *old_clip, SPObject *clip, SPItem *item)
SPItemView *v;
/* Hide clippath */
for (v = item->display; v != NULL; v = v->next) {
- SP_CLIPPATH(old_clip)->hide(NR_ARENA_ITEM_GET_KEY(v->arenaitem));
- nr_arena_item_set_clip(v->arenaitem, NULL);
+ SP_CLIPPATH(old_clip)->hide(v->arenaitem->key());
}
}
if (SP_IS_CLIPPATH(clip)) {
NRRect bbox;
item->invoke_bbox( &bbox, Geom::identity(), TRUE);
for (SPItemView *v = item->display; v != NULL; v = v->next) {
- if (!v->arenaitem->key) {
- NR_ARENA_ITEM_SET_KEY(v->arenaitem, SPItem::display_key_new(3));
+ if (!v->arenaitem->key()) {
+ v->arenaitem->setKey(SPItem::display_key_new(3));
}
- NRArenaItem *ai = SP_CLIPPATH(clip)->show(
- NR_ARENA_ITEM_ARENA(v->arenaitem),
- NR_ARENA_ITEM_GET_KEY(v->arenaitem));
- nr_arena_item_set_clip(v->arenaitem, ai);
- nr_arena_item_unref(ai);
- SP_CLIPPATH(clip)->setBBox(NR_ARENA_ITEM_GET_KEY(v->arenaitem), &bbox);
+ Inkscape::DrawingItem *ai = SP_CLIPPATH(clip)->show(
+ v->arenaitem->drawing(),
+ v->arenaitem->key());
+ v->arenaitem->setClip(ai);
+ SP_CLIPPATH(clip)->setBBox(v->arenaitem->key(), &bbox);
clip->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
}
@@ -556,23 +536,21 @@ void SPItem::mask_ref_changed(SPObject *old_mask, SPObject *mask, SPItem *item)
if (old_mask) {
/* Hide mask */
for (SPItemView *v = item->display; v != NULL; v = v->next) {
- sp_mask_hide(SP_MASK(old_mask), NR_ARENA_ITEM_GET_KEY(v->arenaitem));
- nr_arena_item_set_mask(v->arenaitem, NULL);
+ sp_mask_hide(SP_MASK(old_mask), v->arenaitem->key());
}
}
if (SP_IS_MASK(mask)) {
NRRect bbox;
item->invoke_bbox( &bbox, Geom::identity(), TRUE);
for (SPItemView *v = item->display; v != NULL; v = v->next) {
- if (!v->arenaitem->key) {
- NR_ARENA_ITEM_SET_KEY(v->arenaitem, SPItem::display_key_new(3));
+ if (!v->arenaitem->key()) {
+ v->arenaitem->setKey(SPItem::display_key_new(3));
}
- NRArenaItem *ai = sp_mask_show(SP_MASK(mask),
- NR_ARENA_ITEM_ARENA(v->arenaitem),
- NR_ARENA_ITEM_GET_KEY(v->arenaitem));
- nr_arena_item_set_mask(v->arenaitem, ai);
- nr_arena_item_unref(ai);
- sp_mask_set_bbox(SP_MASK(mask), NR_ARENA_ITEM_GET_KEY(v->arenaitem), &bbox);
+ Inkscape::DrawingItem *ai = sp_mask_show(SP_MASK(mask),
+ v->arenaitem->drawing(),
+ v->arenaitem->key());
+ v->arenaitem->setMask(ai);
+ sp_mask_set_bbox(SP_MASK(mask), v->arenaitem->key(), &bbox);
mask->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
}
@@ -589,7 +567,7 @@ void SPItem::sp_item_update(SPObject *object, SPCtx *ctx, guint flags)
if (flags & (SP_OBJECT_CHILD_MODIFIED_FLAG | SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG)) {
if (flags & SP_OBJECT_MODIFIED_FLAG) {
for (SPItemView *v = item->display; v != NULL; v = v->next) {
- nr_arena_item_set_transform(v->arenaitem, item->transform);
+ v->arenaitem->setTransform(item->transform);
}
}
@@ -601,20 +579,20 @@ void SPItem::sp_item_update(SPObject *object, SPCtx *ctx, guint flags)
item->invoke_bbox( &bbox, Geom::identity(), TRUE);
if (clip_path) {
for (SPItemView *v = item->display; v != NULL; v = v->next) {
- clip_path->setBBox(NR_ARENA_ITEM_GET_KEY(v->arenaitem), &bbox);
+ clip_path->setBBox(v->arenaitem->key(), &bbox);
}
}
if (mask) {
for (SPItemView *v = item->display; v != NULL; v = v->next) {
- sp_mask_set_bbox(mask, NR_ARENA_ITEM_GET_KEY(v->arenaitem), &bbox);
+ sp_mask_set_bbox(mask, v->arenaitem->key(), &bbox);
}
}
}
if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) {
for (SPItemView *v = item->display; v != NULL; v = v->next) {
- nr_arena_item_set_opacity(v->arenaitem, SP_SCALE24_TO_FLOAT(object->style->opacity.value));
- nr_arena_item_set_visible(v->arenaitem, !item->isHidden());
+ v->arenaitem->setOpacity(SP_SCALE24_TO_FLOAT(object->style->opacity.value));
+ v->arenaitem->setVisible(!item->isHidden());
}
}
}
@@ -627,7 +605,7 @@ void SPItem::sp_item_update(SPObject *object, SPCtx *ctx, guint flags)
SPItemView *itemview = item->display;
do {
if (itemview->arenaitem)
- nr_arena_item_set_item_bbox(itemview->arenaitem, item_bbox);
+ itemview->arenaitem->setItemBounds(item_bbox);
} while ( (itemview = itemview->next) );
}
@@ -1025,34 +1003,30 @@ unsigned SPItem::display_key_new(unsigned numkeys)
return dkey - numkeys;
}
-NRArenaItem *SPItem::invoke_show(NRArena *arena, unsigned key, unsigned flags)
+Inkscape::DrawingItem *SPItem::invoke_show(Inkscape::Drawing &drawing, unsigned key, unsigned flags)
{
- g_assert(arena != NULL);
- g_assert(NR_IS_ARENA(arena));
-
- NRArenaItem *ai = NULL;
+ Inkscape::DrawingItem *ai = NULL;
if (((SPItemClass *) G_OBJECT_GET_CLASS(this))->show) {
- ai = ((SPItemClass *) G_OBJECT_GET_CLASS(this))->show(this, arena, key, flags);
+ ai = ((SPItemClass *) G_OBJECT_GET_CLASS(this))->show(this, drawing, key, flags);
}
if (ai != NULL) {
display = sp_item_view_new_prepend(display, this, flags, key, ai);
- nr_arena_item_set_transform(ai, transform);
- nr_arena_item_set_opacity(ai, SP_SCALE24_TO_FLOAT(style->opacity.value));
- nr_arena_item_set_visible(ai, !isHidden());
- nr_arena_item_set_sensitive(ai, sensitive);
+ ai->setTransform(transform);
+ ai->setOpacity(SP_SCALE24_TO_FLOAT(style->opacity.value));
+ ai->setVisible(!isHidden());
+ ai->setSensitive(sensitive);
if (clip_ref->getObject()) {
SPClipPath *cp = clip_ref->getObject();
- if (!display->arenaitem->key) {
- NR_ARENA_ITEM_SET_KEY(display->arenaitem, display_key_new(3));
+ if (!display->arenaitem->key()) {
+ display->arenaitem->setKey(display_key_new(3));
}
- int clip_key = NR_ARENA_ITEM_GET_KEY(display->arenaitem);
+ int clip_key = display->arenaitem->key();
// Show and set clip
- NRArenaItem *ac = cp->show(arena, clip_key);
- nr_arena_item_set_clip(ai, ac);
- nr_arena_item_unref(ac);
+ Inkscape::DrawingItem *ac = cp->show(drawing, clip_key);
+ ai->setClip(ac);
// Update bbox, in case the clip uses bbox units
NRRect bbox;
@@ -1063,15 +1037,14 @@ NRArenaItem *SPItem::invoke_show(NRArena *arena, unsigned key, unsigned flags)
if (mask_ref->getObject()) {
SPMask *mask = mask_ref->getObject();
- if (!display->arenaitem->key) {
- NR_ARENA_ITEM_SET_KEY(display->arenaitem, display_key_new(3));
+ if (!display->arenaitem->key()) {
+ display->arenaitem->setKey(display_key_new(3));
}
- int mask_key = NR_ARENA_ITEM_GET_KEY(display->arenaitem);
+ int mask_key = display->arenaitem->key();
// Show and set mask
- NRArenaItem *ac = sp_mask_show(mask, arena, mask_key);
- nr_arena_item_set_mask(ai, ac);
- nr_arena_item_unref(ac);
+ Inkscape::DrawingItem *ac = sp_mask_show(mask, drawing, mask_key);
+ ai->setMask(ac);
// Update bbox, in case the mask uses bbox units
NRRect bbox;
@@ -1079,10 +1052,10 @@ NRArenaItem *SPItem::invoke_show(NRArena *arena, unsigned key, unsigned flags)
sp_mask_set_bbox(SP_MASK(mask), mask_key, &bbox);
mask->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
- NR_ARENA_ITEM_SET_DATA(ai, this);
+ ai->setData(this);
Geom::OptRect item_bbox;
invoke_bbox( item_bbox, Geom::identity(), TRUE, SPItem::GEOMETRIC_BBOX);
- nr_arena_item_set_item_bbox(ai, item_bbox);
+ ai->setItemBounds(item_bbox);
}
return ai;
@@ -1100,20 +1073,19 @@ void SPItem::invoke_hide(unsigned key)
SPItemView *next = v->next;
if (v->key == key) {
if (clip_ref->getObject()) {
- (clip_ref->getObject())->hide(NR_ARENA_ITEM_GET_KEY(v->arenaitem));
- nr_arena_item_set_clip(v->arenaitem, NULL);
+ (clip_ref->getObject())->hide(v->arenaitem->key());
+ v->arenaitem->setClip(NULL);
}
if (mask_ref->getObject()) {
- sp_mask_hide(mask_ref->getObject(), NR_ARENA_ITEM_GET_KEY(v->arenaitem));
- nr_arena_item_set_mask(v->arenaitem, NULL);
+ sp_mask_hide(mask_ref->getObject(), v->arenaitem->key());
+ v->arenaitem->setMask(NULL);
}
if (!ref) {
display = v->next;
} else {
ref->next = v->next;
}
- nr_arena_item_unparent(v->arenaitem);
- nr_arena_item_unref(v->arenaitem);
+ delete v->arenaitem;
g_free(v);
} else {
ref = v;
@@ -1497,27 +1469,27 @@ Geom::Affine SPItem::dt2i_affine() const
/* Item views */
-SPItemView *SPItem::sp_item_view_new_prepend(SPItemView *list, SPItem *item, unsigned flags, unsigned key, NRArenaItem *arenaitem)
+SPItemView *SPItem::sp_item_view_new_prepend(SPItemView *list, SPItem *item, unsigned flags, unsigned key, Inkscape::DrawingItem *drawing_item)
{
g_assert(item != NULL);
g_assert(SP_IS_ITEM(item));
- g_assert(arenaitem != NULL);
- g_assert(NR_IS_ARENA_ITEM(arenaitem));
+ g_assert(drawing_item != NULL);
SPItemView *new_view = g_new(SPItemView, 1);
new_view->next = list;
new_view->flags = flags;
new_view->key = key;
- new_view->arenaitem = arenaitem;
+ new_view->arenaitem = drawing_item;
return new_view;
}
SPItemView *SPItem::sp_item_view_list_remove(SPItemView *list, SPItemView *view)
{
+ SPItemView *ret = list;
if (view == list) {
- list = list->next;
+ ret = list->next;
} else {
SPItemView *prev;
prev = list;
@@ -1525,17 +1497,17 @@ SPItemView *SPItem::sp_item_view_list_remove(SPItemView *list, SPItemView *view)
prev->next = view->next;
}
- nr_arena_item_unref(view->arenaitem);
+ delete view->arenaitem;
g_free(view);
- return list;
+ return ret;
}
/**
* Return the arenaitem corresponding to the given item in the display
* with the given key
*/
-NRArenaItem *SPItem::get_arenaitem(unsigned key)
+Inkscape::DrawingItem *SPItem::get_arenaitem(unsigned key)
{
for ( SPItemView *iv = display ; iv ; iv = iv->next ) {
if ( iv->key == key ) {
diff --git a/src/sp-item.h b/src/sp-item.h
index 0065a9c0e..633deb508 100644
--- a/src/sp-item.h
+++ b/src/sp-item.h
@@ -20,7 +20,7 @@
*/
#include <vector>
-#include "display/nr-arena-forward.h"
+#include "display/display-forward.h"
#include "sp-object.h"
#include <2geom/affine.h>
#include <libnr/nr-rect.h>
@@ -66,7 +66,7 @@ public:
SPItemView *next;
unsigned int flags;
unsigned int key;
- NRArenaItem *arenaitem;
+ Inkscape::DrawingItem *arenaitem;
};
/* flags */
@@ -169,9 +169,6 @@ public:
Geom::OptRect getBounds(Geom::Affine const &transform, BBoxType type=APPROXIMATE_BBOX, unsigned int dkey=0) const;
- sigc::connection _clip_ref_connection;
- sigc::connection _mask_ref_connection;
-
sigc::connection connectTransformed(sigc::slot<void, Geom::Affine const *, SPItem *> slot) {
return _transformed_signal.connect(slot);
}
@@ -184,7 +181,7 @@ public:
gchar *description();
void invoke_print(SPPrintContext *ctx);
static unsigned int display_key_new(unsigned int numkeys);
- NRArenaItem *invoke_show(NRArena *arena, unsigned int key, unsigned int flags);
+ Inkscape::DrawingItem *invoke_show(Inkscape::Drawing &drawing, unsigned int key, unsigned int flags);
void invoke_hide(unsigned int key);
void getSnappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs=0) const;
void adjust_pattern(/* Geom::Affine const &premul, */ Geom::Affine const &postmul, bool set = false);
@@ -197,7 +194,7 @@ public:
void set_item_transform(Geom::Affine const &transform_matrix);
void convert_item_to_guides();
gint emitEvent (SPEvent &event);
- NRArenaItem *get_arenaitem(unsigned int key);
+ Inkscape::DrawingItem *get_arenaitem(unsigned int key);
void getBboxDesktop(NRRect *bbox, SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX) __attribute__ ((deprecated));
Geom::OptRect getBboxDesktop(SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX);
Geom::Affine i2doc_affine() const;
@@ -226,7 +223,7 @@ private:
static gchar *sp_item_private_description(SPItem *item);
static void sp_item_private_snappoints(SPItem const *item, std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs);
- static SPItemView *sp_item_view_new_prepend(SPItemView *list, SPItem *item, unsigned flags, unsigned key, NRArenaItem *arenaitem);
+ static SPItemView *sp_item_view_new_prepend(SPItemView *list, SPItem *item, unsigned flags, unsigned key, Inkscape::DrawingItem *arenaitem);
static SPItemView *sp_item_view_list_remove(SPItemView *list, SPItemView *view);
static void clip_ref_changed(SPObject *old_clip, SPObject *clip, SPItem *item);
static void mask_ref_changed(SPObject *old_clip, SPObject *clip, SPItem *item);
@@ -249,7 +246,7 @@ public:
/** Give short description of item (for status display) */
gchar * (* description) (SPItem * item);
- NRArenaItem * (* show) (SPItem *item, NRArena *arena, unsigned int key, unsigned int flags);
+ Inkscape::DrawingItem * (* show) (SPItem *item, Inkscape::Drawing &drawing, unsigned int key, unsigned int flags);
void (* hide) (SPItem *item, unsigned int key);
/** Write to an iterator the points that should be considered for snapping
diff --git a/src/sp-mask.cpp b/src/sp-mask.cpp
index 38599188f..f23172a17 100644
--- a/src/sp-mask.cpp
+++ b/src/sp-mask.cpp
@@ -15,8 +15,8 @@
#include <string>
#include <2geom/transforms.h>
-#include "display/nr-arena.h"
-#include "display/nr-arena-group.h"
+#include "display/drawing.h"
+#include "display/drawing-group.h"
#include "xml/repr.h"
#include "enums.h"
@@ -30,7 +30,7 @@
struct SPMaskView {
SPMaskView *next;
unsigned int key;
- NRArenaItem *arenaitem;
+ Inkscape::DrawingItem *arenaitem;
NRRect bbox;
};
@@ -45,7 +45,7 @@ static void sp_mask_update (SPObject *object, SPCtx *ctx, guint flags);
static void sp_mask_modified (SPObject *object, guint flags);
static Inkscape::XML::Node *sp_mask_write (SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags);
-SPMaskView *sp_mask_view_new_prepend (SPMaskView *list, unsigned int key, NRArenaItem *arenaitem);
+SPMaskView *sp_mask_view_new_prepend (SPMaskView *list, unsigned int key, Inkscape::DrawingItem *arenaitem);
SPMaskView *sp_mask_view_list_remove (SPMaskView *list, SPMaskView *view);
static SPObjectGroupClass *parent_class;
@@ -179,11 +179,11 @@ sp_mask_child_added (SPObject *object, Inkscape::XML::Node *child, Inkscape::XML
if (SP_IS_ITEM (ochild)) {
SPMask *cp = SP_MASK (object);
for (SPMaskView *v = cp->display; v != NULL; v = v->next) {
- NRArenaItem *ac = SP_ITEM (ochild)->invoke_show ( NR_ARENA_ITEM_ARENA (v->arenaitem),
+ Inkscape::DrawingItem *ac = SP_ITEM (ochild)->invoke_show ( v->arenaitem->drawing(),
v->key,
SP_ITEM_REFERENCE_FLAGS);
if (ac) {
- nr_arena_item_add_child (v->arenaitem, ac, NULL);
+ v->arenaitem->prependChild(ac);
}
}
}
@@ -215,13 +215,14 @@ static void sp_mask_update(SPObject *object, SPCtx *ctx, guint flags)
SPMask *mask = SP_MASK(object);
for (SPMaskView *v = mask->display; v != NULL; v = v->next) {
+ Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem);
if (mask->maskContentUnits == SP_CONTENT_UNITS_OBJECTBOUNDINGBOX) {
Geom::Affine t(Geom::Scale(v->bbox.x1 - v->bbox.x0, v->bbox.y1 - v->bbox.y0));
t[4] = v->bbox.x0;
t[5] = v->bbox.y0;
- nr_arena_group_set_child_transform(NR_ARENA_GROUP(v->arenaitem), &t);
+ g->setChildTransform(t);
} else {
- nr_arena_group_set_child_transform(NR_ARENA_GROUP(v->arenaitem), NULL);
+ g->setChildTransform(Geom::identity());
}
}
}
@@ -296,22 +297,19 @@ sp_mask_create (GSList *reprs, SPDocument *document, Geom::Affine const* applyTr
return mask_id;
}
-NRArenaItem *sp_mask_show(SPMask *mask, NRArena *arena, unsigned int key)
+Inkscape::DrawingItem *sp_mask_show(SPMask *mask, Inkscape::Drawing &drawing, unsigned int key)
{
g_return_val_if_fail (mask != NULL, NULL);
g_return_val_if_fail (SP_IS_MASK (mask), NULL);
- g_return_val_if_fail (arena != NULL, NULL);
- g_return_val_if_fail (NR_IS_ARENA (arena), NULL);
- NRArenaItem *ai = NRArenaGroup::create(arena);
+ Inkscape::DrawingGroup *ai = new Inkscape::DrawingGroup(drawing);
mask->display = sp_mask_view_new_prepend (mask->display, key, ai);
for ( SPObject *child = mask->firstChild() ; child; child = child->getNext() ) {
if (SP_IS_ITEM (child)) {
- NRArenaItem *ac = SP_ITEM (child)->invoke_show (arena, key, SP_ITEM_REFERENCE_FLAGS);
+ Inkscape::DrawingItem *ac = SP_ITEM (child)->invoke_show (drawing, key, SP_ITEM_REFERENCE_FLAGS);
if (ac) {
- /* The order is not important in mask */
- nr_arena_item_add_child (ai, ac, NULL);
+ ai->prependChild(ac);
}
}
}
@@ -320,7 +318,7 @@ NRArenaItem *sp_mask_show(SPMask *mask, NRArena *arena, unsigned int key)
Geom::Affine t(Geom::Scale(mask->display->bbox.x1 - mask->display->bbox.x0, mask->display->bbox.y1 - mask->display->bbox.y0));
t[4] = mask->display->bbox.x0;
t[5] = mask->display->bbox.y0;
- nr_arena_group_set_child_transform (NR_ARENA_GROUP (ai), &t);
+ ai->setChildTransform(t);
}
return ai;
@@ -367,13 +365,13 @@ sp_mask_set_bbox (SPMask *mask, unsigned int key, NRRect *bbox)
/* Mask views */
SPMaskView *
-sp_mask_view_new_prepend (SPMaskView *list, unsigned int key, NRArenaItem *arenaitem)
+sp_mask_view_new_prepend (SPMaskView *list, unsigned int key, Inkscape::DrawingItem *arenaitem)
{
SPMaskView *new_mask_view = g_new (SPMaskView, 1);
new_mask_view->next = list;
new_mask_view->key = key;
- new_mask_view->arenaitem = nr_arena_item_ref(arenaitem);
+ new_mask_view->arenaitem = arenaitem;
new_mask_view->bbox.x0 = new_mask_view->bbox.x1 = 0.0;
new_mask_view->bbox.y0 = new_mask_view->bbox.y1 = 0.0;
@@ -392,7 +390,7 @@ sp_mask_view_list_remove (SPMaskView *list, SPMaskView *view)
prev->next = view->next;
}
- nr_arena_item_unref (view->arenaitem);
+ delete view->arenaitem;
g_free (view);
return list;
diff --git a/src/sp-mask.h b/src/sp-mask.h
index 5a98ac8c5..b1048e6be 100644
--- a/src/sp-mask.h
+++ b/src/sp-mask.h
@@ -23,7 +23,7 @@ class SPMask;
class SPMaskClass;
class SPMaskView;
-#include "display/nr-arena-forward.h"
+#include "display/display-forward.h"
#include "libnr/nr-forward.h"
#include "sp-object-group.h"
#include "uri-references.h"
@@ -90,7 +90,7 @@ protected:
}
};
-NRArenaItem *sp_mask_show (SPMask *mask, NRArena *arena, unsigned int key);
+Inkscape::DrawingItem *sp_mask_show (SPMask *mask, Inkscape::Drawing &drawing, unsigned int key);
void sp_mask_hide (SPMask *mask, unsigned int key);
void sp_mask_set_bbox (SPMask *mask, unsigned int key, NRRect *bbox);
diff --git a/src/sp-pattern.cpp b/src/sp-pattern.cpp
index d1e7671ed..9aefdf6ff 100644
--- a/src/sp-pattern.cpp
+++ b/src/sp-pattern.cpp
@@ -22,11 +22,14 @@
#include "macros.h"
#include "svg/svg.h"
#include "display/cairo-utils.h"
-#include "display/nr-arena.h"
-#include "display/nr-arena-group.h"
+#include "display/drawing-context.h"
+#include "display/drawing-surface.h"
+#include "display/drawing.h"
+#include "display/drawing-group.h"
#include "attributes.h"
#include "document-private.h"
#include "uri.h"
+#include "style.h"
#include "sp-pattern.h"
#include "xml/repr.h"
#include "display/grayscale.h"
@@ -627,18 +630,19 @@ sp_pattern_create_pattern(SPPaintServer *ps,
return cairo_pattern_create_rgba(0,0,0,0);
}
- /* Create arena */
- NRArena *arena = NRArena::create();
+ /* Create drawing for rendering */
+ Inkscape::Drawing drawing;
unsigned int dkey = SPItem::display_key_new (1);
- NRArenaGroup *root = NRArenaGroup::create(arena);
+ Inkscape::DrawingGroup *root = new Inkscape::DrawingGroup(drawing);
+ drawing.setRoot(root);
for (SPObject *child = shown->firstChild(); child != NULL; child = child->getNext() ) {
if (SP_IS_ITEM (child)) {
- // for each item in pattern, show it on our arena, add to the group,
+ // for each item in pattern, show it on our drawing, add to the group,
// and connect to the release signal in case the item gets deleted
- NRArenaItem *cai;
- cai = SP_ITEM(child)->invoke_show (arena, dkey, SP_ITEM_SHOW_DISPLAY);
- nr_arena_item_append_child (root, cai);
+ Inkscape::DrawingItem *cai;
+ cai = SP_ITEM(child)->invoke_show (drawing, dkey, SP_ITEM_SHOW_DISPLAY);
+ root->appendChild(cai);
}
}
@@ -658,9 +662,8 @@ sp_pattern_create_pattern(SPPaintServer *ps,
}
ps2user = Geom::Translate (pattern_x (pat), pattern_y (pat)) * ps2user;
- Geom::Point p(pattern_x(pat), pattern_y(pat));
- Geom::Point pd(pattern_width(pat), pattern_height(pat));
- Geom::Rect pattern_tile(p, p + pd);
+ Geom::Rect pattern_tile = Geom::Rect::from_xywh(pattern_x(pat), pattern_y(pat),
+ pattern_width(pat), pattern_height(pat));
if (pattern_patternUnits(pat) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) {
// interpret x, y, width, height in relation to bbox
@@ -674,53 +677,42 @@ sp_pattern_create_pattern(SPPaintServer *ps,
// oversample the pattern slightly
// TODO: find optimum value
- Geom::Point c(pattern_tile.dimensions()*ps2user.descrim()*full.descrim()*1.2);
+ // TODO: this is lame. instead of using descrim(), we should extract
+ // the scaling component from the complete matrix and use it
+ // to find the optimum tile size for rendering
+ Geom::Point c(pattern_tile.dimensions()*vb2ps.descrim()*ps2user.descrim()*full.descrim()*1.1);
c[Geom::X] = ceil(c[Geom::X]);
c[Geom::Y] = ceil(c[Geom::Y]);
- Geom::Affine t = Geom::Scale(c) * Geom::Scale(pattern_tile.dimensions()).inverse();
-
- NRRectL one_tile;
- one_tile.x0 = (int) floor(pattern_tile[Geom::X].min());
- one_tile.y0 = (int) floor(pattern_tile[Geom::Y].min());
- one_tile.x1 = (int) ceil(pattern_tile[Geom::X].max());
- one_tile.y1 = (int) ceil(pattern_tile[Geom::Y].max());
-
- cairo_surface_t *target = cairo_get_target(base_ct);
- cairo_surface_t *temp = cairo_surface_create_similar(target, CAIRO_CONTENT_COLOR_ALPHA,
- c[Geom::X], c[Geom::Y]);
- cairo_t *ct = cairo_create(temp);
- // scale into a coord system where the surface w,h are equal to tile w,h
- ink_cairo_transform(ct, t);
+
+ Geom::IntRect one_tile = pattern_tile.roundOutwards();
+ Inkscape::DrawingSurface temp(pattern_tile, c.ceil());
+ Inkscape::DrawingContext ct(temp);
// render pattern.
if (needs_opacity) {
- cairo_push_group(ct); // this group is for pattern + opacity
+ ct.pushGroup(); // this group is for pattern + opacity
}
// TODO: make sure there are no leaks.
- NRGC gc(NULL);
- gc.transform = vb2ps;
- nr_arena_item_invoke_update (root, NULL, &gc, NR_ARENA_ITEM_STATE_ALL, NR_ARENA_ITEM_STATE_ALL);
- nr_arena_item_invoke_render (ct, root, &one_tile, NULL, 0);
+ Inkscape::UpdateContext ctx;
+ ctx.ctm = vb2ps;
+ drawing.update(Geom::IntRect::infinite(), ctx);
+ drawing.render(ct, one_tile);
for (SPObject *child = shown->firstChild() ; child != NULL; child = child->getNext() ) {
if (SP_IS_ITEM (child)) {
SP_ITEM(child)->invoke_hide(dkey);
}
}
- nr_object_unref(root);
- nr_object_unref(arena);
if (needs_opacity) {
- cairo_pop_group_to_source(ct); // pop raw pattern
- cairo_paint_with_alpha(ct, opacity); // apply opacity
+ ct.popGroupToSource(); // pop raw pattern
+ ct.paint(opacity); // apply opacity
}
- cairo_pattern_t *cp = cairo_pattern_create_for_surface(temp);
- cairo_destroy(ct);
- cairo_surface_destroy(temp);
+ cairo_pattern_t *cp = cairo_pattern_create_for_surface(temp.raw());
// Apply transformation to user space. Also compensate for oversampling.
- ink_cairo_pattern_set_matrix(cp, ps2user.inverse() * t);
+ ink_cairo_pattern_set_matrix(cp, ps2user.inverse() * temp.drawingTransform());
cairo_pattern_set_extend(cp, CAIRO_EXTEND_REPEAT);
return cp;
diff --git a/src/sp-root.cpp b/src/sp-root.cpp
index 918bd3295..a6df580d3 100644
--- a/src/sp-root.cpp
+++ b/src/sp-root.cpp
@@ -22,7 +22,7 @@
#include <2geom/transforms.h>
#include "svg/svg.h"
-#include "display/nr-arena-group.h"
+#include "display/drawing-group.h"
#include "attributes.h"
#include "print.h"
#include "document.h"
@@ -46,7 +46,7 @@ static void sp_root_update(SPObject *object, SPCtx *ctx, guint flags);
static void sp_root_modified(SPObject *object, guint flags);
static Inkscape::XML::Node *sp_root_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags);
-static NRArenaItem *sp_root_show(SPItem *item, NRArena *arena, unsigned int key, unsigned int flags);
+static Inkscape::DrawingItem *sp_root_show(SPItem *item, Inkscape::Drawing &drawing, unsigned int key, unsigned int flags);
static void sp_root_print(SPItem *item, SPPrintContext *ctx);
static SPGroupClass *parent_class;
@@ -538,9 +538,10 @@ static void sp_root_update(SPObject *object, SPCtx *ctx, guint flags)
if (((SPObjectClass *) (parent_class))->update)
((SPObjectClass *) (parent_class))->update(object, (SPCtx *) &rctx, flags);
- /* As last step set additional transform of arena group */
+ /* As last step set additional transform of drawing group */
for (SPItemView *v = root->display; v != NULL; v = v->next) {
- nr_arena_group_set_child_transform(NR_ARENA_GROUP(v->arenaitem), root->c2p);
+ Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem);
+ g->setChildTransform(root->c2p);
}
}
@@ -607,18 +608,19 @@ sp_root_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML:
}
/**
- * Displays the SPRoot item on the NRArena.
+ * Displays the SPRoot item on the drawing.
*/
-static NRArenaItem *
-sp_root_show(SPItem *item, NRArena *arena, unsigned int key, unsigned int flags)
+static Inkscape::DrawingItem *
+sp_root_show(SPItem *item, Inkscape::Drawing &drawing, unsigned int key, unsigned int flags)
{
SPRoot *root = SP_ROOT(item);
- NRArenaItem *ai;
+ Inkscape::DrawingItem *ai;
if (((SPItemClass *) (parent_class))->show) {
- ai = ((SPItemClass *) (parent_class))->show(item, arena, key, flags);
+ ai = ((SPItemClass *) (parent_class))->show(item, drawing, key, flags);
if (ai) {
- nr_arena_group_set_child_transform(NR_ARENA_GROUP(ai), root->c2p);
+ Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(ai);
+ g->setChildTransform(root->c2p);
}
} else {
ai = NULL;
diff --git a/src/sp-shape.cpp b/src/sp-shape.cpp
index 7f24dd089..4fd1deb69 100644
--- a/src/sp-shape.cpp
+++ b/src/sp-shape.cpp
@@ -30,7 +30,7 @@
#include <sigc++/adaptors/bind.h>
#include "macros.h"
-#include "display/nr-arena-shape.h"
+#include "display/drawing-shape.h"
#include "display/curve.h"
#include "print.h"
#include "document.h"
@@ -182,7 +182,7 @@ void SPShape::sp_shape_release(SPObject *object)
for (i = 0; i < SP_MARKER_LOC_QTY; i++) {
if (shape->marker[i]) {
for (v = item->display; v != NULL; v = v->next) {
- sp_marker_hide ((SPMarker *) shape->marker[i], NR_ARENA_ITEM_GET_KEY (v->arenaitem) + i);
+ sp_marker_hide ((SPMarker *) shape->marker[i], v->arenaitem->key() + i);
}
shape->release_connect[i].disconnect();
shape->modified_connect[i].disconnect();
@@ -247,7 +247,8 @@ void SPShape::sp_shape_update(SPObject *object, SPCtx *ctx, unsigned int flags)
double const aw = 1.0 / ictx->i2vp.descrim();
style->stroke_width.computed = style->stroke_width.value * aw;
for (SPItemView *v = ((SPItem *) (shape))->display; v != NULL; v = v->next) {
- nr_arena_shape_set_style ((NRArenaShape *) v->arenaitem, style);
+ Inkscape::DrawingShape *sh = dynamic_cast<Inkscape::DrawingShape *>(v->arenaitem);
+ sh->setStyle(style);
}
}
}
@@ -255,14 +256,10 @@ void SPShape::sp_shape_update(SPObject *object, SPCtx *ctx, unsigned int flags)
if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_PARENT_MODIFIED_FLAG)) {
/* This is suboptimal, because changing parent style schedules recalculation */
/* But on the other hand - how can we know that parent does not tie style and transform */
- Geom::OptRect paintbox = SP_ITEM(object)->getBounds(Geom::identity(), SPItem::GEOMETRIC_BBOX);
for (SPItemView *v = shape->display; v != NULL; v = v->next) {
- NRArenaShape * const s = NR_ARENA_SHAPE(v->arenaitem);
+ Inkscape::DrawingShape *sh = dynamic_cast<Inkscape::DrawingShape *>(v->arenaitem);
if (flags & SP_OBJECT_MODIFIED_FLAG) {
- nr_arena_shape_set_path(s, shape->curve, (flags & SP_OBJECT_USER_MODIFIED_FLAG_B));
- }
- if (paintbox) {
- s->setPaintBox(*paintbox);
+ sh->setPath(shape->curve);
}
}
}
@@ -270,13 +267,13 @@ void SPShape::sp_shape_update(SPObject *object, SPCtx *ctx, unsigned int flags)
if (shape->hasMarkers ()) {
/* Dimension marker views */
for (SPItemView *v = shape->display; v != NULL; v = v->next) {
- if (!v->arenaitem->key) {
- NR_ARENA_ITEM_SET_KEY (v->arenaitem, SPItem::display_key_new (SP_MARKER_LOC_QTY));
+ if (!v->arenaitem->key()) {
+ v->arenaitem->setKey(SPItem::display_key_new (SP_MARKER_LOC_QTY));
}
for (int i = 0 ; i < SP_MARKER_LOC_QTY ; i++) {
if (shape->marker[i]) {
sp_marker_show_dimension ((SPMarker *) shape->marker[i],
- NR_ARENA_ITEM_GET_KEY (v->arenaitem) + i,
+ v->arenaitem->key() + i,
shape->numberOfMarkers (i));
}
}
@@ -375,7 +372,7 @@ Geom::Affine sp_shape_marker_get_transform_at_end(Geom::Curve const & c)
*
* @todo figure out what to do when both 'marker' and for instance 'marker-end' are set.
*/
-void SPShape::sp_shape_update_marker_view(SPShape *shape, NRArenaItem *ai)
+void SPShape::sp_shape_update_marker_view(SPShape *shape, Inkscape::DrawingItem *ai)
{
SPStyle *style = ((SPObject *) shape)->style;
@@ -395,7 +392,7 @@ void SPShape::sp_shape_update_marker_view(SPShape *shape, NRArenaItem *ai)
for (int i = 0; i < 2; i++) { // SP_MARKER_LOC and SP_MARKER_LOC_START
if ( shape->marker[i] ) {
sp_marker_show_instance ((SPMarker* ) shape->marker[i], ai,
- NR_ARENA_ITEM_GET_KEY(ai) + i, counter[i], m,
+ ai->key() + i, counter[i], m,
style->stroke_width.computed);
counter[i]++;
}
@@ -413,7 +410,7 @@ void SPShape::sp_shape_update_marker_view(SPShape *shape, NRArenaItem *ai)
for (int i = 0; i < 3; i += 2) { // SP_MARKER_LOC and SP_MARKER_LOC_MID
if ( shape->marker[i] ) {
sp_marker_show_instance ((SPMarker* ) shape->marker[i], ai,
- NR_ARENA_ITEM_GET_KEY(ai) + i, counter[i], m,
+ ai->key() + i, counter[i], m,
style->stroke_width.computed);
counter[i]++;
}
@@ -433,7 +430,7 @@ void SPShape::sp_shape_update_marker_view(SPShape *shape, NRArenaItem *ai)
for (int i = 0; i < 3; i += 2) { // SP_MARKER_LOC and SP_MARKER_LOC_MID
if (shape->marker[i]) {
sp_marker_show_instance ((SPMarker* ) shape->marker[i], ai,
- NR_ARENA_ITEM_GET_KEY(ai) + i, counter[i], m,
+ ai->key() + i, counter[i], m,
style->stroke_width.computed);
counter[i]++;
}
@@ -450,7 +447,7 @@ void SPShape::sp_shape_update_marker_view(SPShape *shape, NRArenaItem *ai)
for (int i = 0; i < 3; i += 2) { // SP_MARKER_LOC and SP_MARKER_LOC_MID
if (shape->marker[i]) {
sp_marker_show_instance ((SPMarker* ) shape->marker[i], ai,
- NR_ARENA_ITEM_GET_KEY(ai) + i, counter[i], m,
+ ai->key() + i, counter[i], m,
style->stroke_width.computed);
counter[i]++;
}
@@ -474,7 +471,7 @@ void SPShape::sp_shape_update_marker_view(SPShape *shape, NRArenaItem *ai)
for (int i = 0; i < 4; i += 3) { // SP_MARKER_LOC and SP_MARKER_LOC_END
if (shape->marker[i]) {
sp_marker_show_instance ((SPMarker* ) shape->marker[i], ai,
- NR_ARENA_ITEM_GET_KEY(ai) + i, counter[i], m,
+ ai->key() + i, counter[i], m,
style->stroke_width.computed);
counter[i]++;
}
@@ -495,7 +492,8 @@ void SPShape::sp_shape_modified(SPObject *object, unsigned int flags)
if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) {
for (SPItemView *v = shape->display; v != NULL; v = v->next) {
- nr_arena_shape_set_style (NR_ARENA_SHAPE (v->arenaitem), object->style);
+ Inkscape::DrawingShape *sh = dynamic_cast<Inkscape::DrawingShape *>(v->arenaitem);
+ sh->setStyle(object->style);
}
}
}
@@ -850,19 +848,14 @@ sp_shape_print (SPItem *item, SPPrintContext *ctx)
/**
* Sets style, path, and paintbox. Updates marker views, including dimensions.
*/
-NRArenaItem * SPShape::sp_shape_show(SPItem *item, NRArena *arena, unsigned int /*key*/, unsigned int /*flags*/)
+Inkscape::DrawingItem * SPShape::sp_shape_show(SPItem *item, Inkscape::Drawing &drawing, unsigned int /*key*/, unsigned int /*flags*/)
{
SPObject *object = item;
SPShape *shape = SP_SHAPE(item);
- NRArenaItem *arenaitem = NRArenaShape::create(arena);
- NRArenaShape * const s = NR_ARENA_SHAPE(arenaitem);
- nr_arena_shape_set_style(s, object->style);
- nr_arena_shape_set_path(s, shape->curve, false);
- Geom::OptRect paintbox = item->getBounds(Geom::identity());
- if (paintbox) {
- s->setPaintBox(*paintbox);
- }
+ Inkscape::DrawingShape *s = new Inkscape::DrawingShape(drawing);
+ s->setStyle(object->style);
+ s->setPath(shape->curve);
/* This stanza checks that an object's marker style agrees with
* the marker objects it has allocated. sp_shape_set_marker ensures
@@ -876,23 +869,23 @@ NRArenaItem * SPShape::sp_shape_show(SPItem *item, NRArena *arena, unsigned int
if (shape->hasMarkers ()) {
/* provide key and dimension the marker views */
- if (!arenaitem->key) {
- NR_ARENA_ITEM_SET_KEY (arenaitem, SPItem::display_key_new (SP_MARKER_LOC_QTY));
+ if (!s->key()) {
+ s->setKey(SPItem::display_key_new (SP_MARKER_LOC_QTY));
}
for (int i = 0; i < SP_MARKER_LOC_QTY; i++) {
if (shape->marker[i]) {
sp_marker_show_dimension ((SPMarker *) shape->marker[i],
- NR_ARENA_ITEM_GET_KEY (arenaitem) + i,
+ s->key() + i,
shape->numberOfMarkers (i));
}
}
/* Update marker views */
- sp_shape_update_marker_view (shape, arenaitem);
+ sp_shape_update_marker_view (shape, s);
}
- return arenaitem;
+ return s;
}
/**
@@ -911,7 +904,7 @@ void SPShape::sp_shape_hide(SPItem *item, unsigned int key)
for (v = item->display; v != NULL; v = v->next) {
if (key == v->key) {
sp_marker_hide ((SPMarker *) shape->marker[i],
- NR_ARENA_ITEM_GET_KEY (v->arenaitem) + i);
+ v->arenaitem->key() + i);
}
}
}
@@ -1013,9 +1006,7 @@ sp_shape_marker_release (SPObject *marker, SPShape *shape)
SPItemView *v;
/* Hide marker */
for (v = item->display; v != NULL; v = v->next) {
- sp_marker_hide ((SPMarker *) (shape->marker[i]), NR_ARENA_ITEM_GET_KEY (v->arenaitem) + i);
- /* fixme: Do we need explicit remove here? (Lauris) */
- /* nr_arena_item_set_mask (v->arenaitem, NULL); */
+ sp_marker_hide ((SPMarker *) (shape->marker[i]), v->arenaitem->key() + i);
}
/* Detach marker */
shape->release_connect[i].disconnect();
@@ -1064,9 +1055,7 @@ sp_shape_set_marker (SPObject *object, unsigned int key, const gchar *value)
/* Hide marker */
for (v = item->display; v != NULL; v = v->next) {
sp_marker_hide ((SPMarker *) (shape->marker[key]),
- NR_ARENA_ITEM_GET_KEY (v->arenaitem) + key);
- /* fixme: Do we need explicit remove here? (Lauris) */
- /* nr_arena_item_set_mask (v->arenaitem, NULL); */
+ v->arenaitem->key() + key);
}
/* Unref marker */
diff --git a/src/sp-shape.h b/src/sp-shape.h
index b91850d1f..355d8e7cc 100644
--- a/src/sp-shape.h
+++ b/src/sp-shape.h
@@ -67,11 +67,11 @@ private:
static Inkscape::XML::Node *sp_shape_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags);
static void sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags);
- static NRArenaItem *sp_shape_show (SPItem *item, NRArena *arena, unsigned int key, unsigned int flags);
+ static Inkscape::DrawingItem *sp_shape_show (SPItem *item, Inkscape::Drawing &drawing, unsigned int key, unsigned int flags);
static void sp_shape_hide (SPItem *item, unsigned int key);
static void sp_shape_snappoints (SPItem const *item, std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs);
- static void sp_shape_update_marker_view (SPShape *shape, NRArenaItem *ai);
+ static void sp_shape_update_marker_view (SPShape *shape, Inkscape::DrawingItem *ai);
diff --git a/src/sp-switch.cpp b/src/sp-switch.cpp
index eb30f2644..500e43c9c 100644
--- a/src/sp-switch.cpp
+++ b/src/sp-switch.cpp
@@ -19,7 +19,7 @@
#include <glibmm/i18n.h>
#include "sp-switch.h"
-#include "display/nr-arena-group.h"
+#include "display/drawing-group.h"
#include "conditions.h"
#include <sigc++/functors/ptr_fun.h>
@@ -117,7 +117,7 @@ void CSwitch::onOrderChanged (Inkscape::XML::Node *, Inkscape::XML::Node *, Inks
_reevaluate();
}
-void CSwitch::_reevaluate(bool /*add_to_arena*/) {
+void CSwitch::_reevaluate(bool /*add_to_drawing*/) {
SPObject *evaluated_child = _evaluateFirst();
if (!evaluated_child || _cached_item == evaluated_child) {
return;
@@ -157,20 +157,18 @@ void CSwitch::_releaseLastItem(SPObject *obj)
_cached_item = NULL;
}
-void CSwitch::_showChildren (NRArena *arena, NRArenaItem *ai, unsigned int key, unsigned int flags) {
+void CSwitch::_showChildren (Inkscape::Drawing &drawing, Inkscape::DrawingItem *ai, unsigned int key, unsigned int flags) {
SPObject *evaluated_child = _evaluateFirst();
- NRArenaItem *ar = NULL;
GSList *l = _childList(false, SPObject::ActionShow);
while (l) {
SPObject *o = SP_OBJECT (l->data);
if (SP_IS_ITEM (o)) {
SPItem * child = SP_ITEM(o);
child->setEvaluated(o == evaluated_child);
- NRArenaItem *ac = child->invoke_show (arena, key, flags);
+ Inkscape::DrawingItem *ac = child->invoke_show (drawing, key, flags);
if (ac) {
- nr_arena_item_add_child (ai, ac, ar);
- ar = ac;
+ ai->appendChild(ac);
}
}
l = g_slist_remove (l, o);
diff --git a/src/sp-switch.h b/src/sp-switch.h
index 310655a23..8eafe6e7b 100644
--- a/src/sp-switch.h
+++ b/src/sp-switch.h
@@ -42,7 +42,7 @@ public:
protected:
virtual GSList *_childList(bool add_ref, SPObject::Action action);
- virtual void _showChildren (NRArena *arena, NRArenaItem *ai, unsigned int key, unsigned int flags);
+ virtual void _showChildren (Inkscape::Drawing &drawing, Inkscape::DrawingItem *ai, unsigned int key, unsigned int flags);
SPObject *_evaluateFirst();
void _reevaluate(bool add_to_arena = false);
diff --git a/src/sp-symbol.cpp b/src/sp-symbol.cpp
index 91218c986..bee28f8e3 100644
--- a/src/sp-symbol.cpp
+++ b/src/sp-symbol.cpp
@@ -19,7 +19,7 @@
#include <string>
#include <2geom/transforms.h>
-#include "display/nr-arena-group.h"
+#include "display/drawing-group.h"
#include "xml/repr.h"
#include "attributes.h"
#include "print.h"
@@ -37,7 +37,7 @@ static void sp_symbol_update (SPObject *object, SPCtx *ctx, guint flags);
static void sp_symbol_modified (SPObject *object, guint flags);
static Inkscape::XML::Node *sp_symbol_write (SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags);
-static NRArenaItem *sp_symbol_show (SPItem *item, NRArena *arena, unsigned int key, unsigned int flags);
+static Inkscape::DrawingItem *sp_symbol_show (SPItem *item, Inkscape::Drawing &drawing, unsigned int key, unsigned int flags);
static void sp_symbol_hide (SPItem *item, unsigned int key);
static void sp_symbol_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags);
static void sp_symbol_print (SPItem *item, SPPrintContext *ctx);
@@ -325,9 +325,10 @@ static void sp_symbol_update(SPObject *object, SPCtx *ctx, guint flags)
((SPObjectClass *) (parent_class))->update (object, (SPCtx *) &rctx, flags);
}
- // As last step set additional transform of arena group
+ // As last step set additional transform of drawing group
for (SPItemView *v = symbol->display; v != NULL; v = v->next) {
- nr_arena_group_set_child_transform(NR_ARENA_GROUP(v->arenaitem), symbol->c2p);
+ Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem);
+ g->setChildTransform(symbol->c2p);
}
} else {
// No-op
@@ -367,17 +368,18 @@ static Inkscape::XML::Node *sp_symbol_write(SPObject *object, Inkscape::XML::Doc
return repr;
}
-static NRArenaItem *sp_symbol_show(SPItem *item, NRArena *arena, unsigned int key, unsigned int flags)
+static Inkscape::DrawingItem *sp_symbol_show(SPItem *item, Inkscape::Drawing &drawing, unsigned int key, unsigned int flags)
{
SPSymbol *symbol = SP_SYMBOL(item);
- NRArenaItem *ai = 0;
+ Inkscape::DrawingItem *ai = 0;
if (symbol->cloned) {
// Cloned <symbol> is actually renderable
if (((SPItemClass *) (parent_class))->show) {
- ai = ((SPItemClass *) (parent_class))->show (item, arena, key, flags);
- if (ai) {
- nr_arena_group_set_child_transform(NR_ARENA_GROUP(ai), symbol->c2p);
+ ai = ((SPItemClass *) (parent_class))->show (item, drawing, key, flags);
+ Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(ai);
+ if (g) {
+ g->setChildTransform(symbol->c2p);
}
}
}
diff --git a/src/sp-text.cpp b/src/sp-text.cpp
index c56f2e91f..9bb674843 100644
--- a/src/sp-text.cpp
+++ b/src/sp-text.cpp
@@ -35,7 +35,7 @@
#include <glibmm/i18n.h>
#include "svg/svg.h"
#include "svg/stringstream.h"
-#include "display/nr-arena-glyphs.h"
+#include "display/drawing-text.h"
#include "attributes.h"
#include "document.h"
#include "desktop-handles.h"
@@ -72,7 +72,7 @@ static void sp_text_modified (SPObject *object, guint flags);
static Inkscape::XML::Node *sp_text_write (SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags);
static void sp_text_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags);
-static NRArenaItem *sp_text_show (SPItem *item, NRArena *arena, unsigned key, unsigned flags);
+static Inkscape::DrawingItem *sp_text_show (SPItem *item, Inkscape::Drawing &drawing, unsigned key, unsigned flags);
static void sp_text_hide (SPItem *item, unsigned key);
static char *sp_text_description (SPItem *item);
static void sp_text_snappoints(SPItem const *item, std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs);
@@ -251,10 +251,11 @@ static void sp_text_update(SPObject *object, SPCtx *ctx, guint flags)
NRRect paintbox;
text->invoke_bbox( &paintbox, Geom::identity(), TRUE);
for (SPItemView* v = text->display; v != NULL; v = v->next) {
- text->_clearFlow(NR_ARENA_GROUP(v->arenaitem));
- nr_arena_group_set_style(NR_ARENA_GROUP(v->arenaitem), object->style);
+ Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem);
+ text->_clearFlow(g);
+ g->setStyle(object->style);
// pass the bbox of the text object as paintbox (used for paintserver fills)
- text->layout.show(NR_ARENA_GROUP(v->arenaitem), &paintbox);
+ text->layout.show(g, &paintbox);
}
}
}
@@ -270,18 +271,19 @@ static void sp_text_modified(SPObject *object, guint flags)
cflags |= SP_OBJECT_PARENT_MODIFIED_FLAG;
}
- // FIXME: all that we need to do here is nr_arena_glyphs_[group_]set_style, to set the changed
- // style, but there's no easy way to access the arena glyphs or glyph groups corresponding to a
- // text object. Therefore we do here the same as in _update, that is, destroy all arena items
+ // FIXME: all that we need to do here is to call setStyle, to set the changed
+ // style, but there's no easy way to access the drawing glyphs or texts corresponding to a
+ // text object. Therefore we do here the same as in _update, that is, destroy all items
// and create new ones. This is probably quite wasteful.
if (flags & ( SP_OBJECT_STYLE_MODIFIED_FLAG )) {
SPText *text = SP_TEXT (object);
NRRect paintbox;
text->invoke_bbox( &paintbox, Geom::identity(), TRUE);
for (SPItemView* v = text->display; v != NULL; v = v->next) {
- text->_clearFlow(NR_ARENA_GROUP(v->arenaitem));
- nr_arena_group_set_style(NR_ARENA_GROUP(v->arenaitem), object->style);
- text->layout.show(NR_ARENA_GROUP(v->arenaitem), &paintbox);
+ Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem);
+ text->_clearFlow(g);
+ g->setStyle(object->style);
+ text->layout.show(g, &paintbox);
}
}
@@ -383,15 +385,14 @@ sp_text_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, un
}
-static NRArenaItem *
-sp_text_show(SPItem *item, NRArena *arena, unsigned /* key*/, unsigned /*flags*/)
+static Inkscape::DrawingItem *
+sp_text_show(SPItem *item, Inkscape::Drawing &drawing, unsigned /* key*/, unsigned /*flags*/)
{
SPText *group = (SPText *) item;
- NRArenaGroup *flowed = NRArenaGroup::create(arena);
- nr_arena_group_set_transparent (flowed, FALSE);
-
- nr_arena_group_set_style(flowed, group->style);
+ Inkscape::DrawingGroup *flowed = new Inkscape::DrawingGroup(drawing);
+ flowed->setPickChildren(false);
+ flowed->setStyle(group->style);
// pass the bbox of the text object as paintbox (used for paintserver fills)
NRRect paintbox;
@@ -662,17 +663,9 @@ void SPText::_adjustCoordsRecursive(SPItem *item, Geom::Affine const &m, double
}
-void SPText::_clearFlow(NRArenaGroup *in_arena)
+void SPText::_clearFlow(Inkscape::DrawingGroup *in_arena)
{
- nr_arena_item_request_render (in_arena);
- for (NRArenaItem *child = in_arena->children; child != NULL; ) {
- NRArenaItem *nchild = child->next;
-
- nr_arena_glyphs_group_clear(NR_ARENA_GLYPHS_GROUP(child));
- nr_arena_item_remove_child (in_arena, child);
-
- child=nchild;
- }
+ in_arena->clearChildren();
}
diff --git a/src/sp-text.h b/src/sp-text.h
index cd103aa2a..e426c425b 100644
--- a/src/sp-text.h
+++ b/src/sp-text.h
@@ -56,8 +56,8 @@ struct SPText : public SPItem {
static void _adjustCoordsRecursive(SPItem *item, Geom::Affine const &m, double ex, bool is_root = true);
static void _adjustFontsizeRecursive(SPItem *item, double ex, bool is_root = true);
- /** discards the NRArena objects representing this text. */
- void _clearFlow(NRArenaGroup *in_arena);
+ /** discards the drawing objects representing this text. */
+ void _clearFlow(Inkscape::DrawingGroup *in_arena);
private:
/** Recursively walks the xml tree adding tags and their contents. The
diff --git a/src/sp-tref.cpp b/src/sp-tref.cpp
index b301add7f..dcf46f6ac 100644
--- a/src/sp-tref.cpp
+++ b/src/sp-tref.cpp
@@ -32,7 +32,6 @@
#include "text-editing.h"
#include "uri.h"
-#include "display/nr-arena-group.h"
#include "xml/node.h"
#include "xml/repr.h"
diff --git a/src/sp-use.cpp b/src/sp-use.cpp
index a05b28a5f..89df9130d 100644
--- a/src/sp-use.cpp
+++ b/src/sp-use.cpp
@@ -22,7 +22,7 @@
#include <2geom/transforms.h>
#include <glibmm/i18n.h>
-#include "display/nr-arena-group.h"
+#include "display/drawing-group.h"
#include "attributes.h"
#include "document.h"
#include "sp-object-repr.h"
@@ -53,7 +53,7 @@ static void sp_use_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &tr
static void sp_use_snappoints(SPItem const *item, std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs);
static void sp_use_print(SPItem *item, SPPrintContext *ctx);
static gchar *sp_use_description(SPItem *item);
-static NRArenaItem *sp_use_show(SPItem *item, NRArena *arena, unsigned key, unsigned flags);
+static Inkscape::DrawingItem *sp_use_show(SPItem *item, Inkscape::Drawing &drawing, unsigned key, unsigned flags);
static void sp_use_hide(SPItem *item, unsigned key);
static void sp_use_href_changed(SPObject *old_ref, SPObject *ref, SPUse *use);
@@ -346,23 +346,23 @@ sp_use_description(SPItem *item)
}
}
-static NRArenaItem *
-sp_use_show(SPItem *item, NRArena *arena, unsigned key, unsigned flags)
+static Inkscape::DrawingItem *
+sp_use_show(SPItem *item, Inkscape::Drawing &drawing, unsigned key, unsigned flags)
{
SPUse *use = SP_USE(item);
- NRArenaItem *ai = NRArenaGroup::create(arena);
- nr_arena_group_set_transparent(NR_ARENA_GROUP(ai), FALSE);
- nr_arena_group_set_style(NR_ARENA_GROUP(ai), item->style);
+ Inkscape::DrawingGroup *ai = new Inkscape::DrawingGroup(drawing);
+ ai->setPickChildren(false);
+ ai->setStyle(item->style);
if (use->child) {
- NRArenaItem *ac = SP_ITEM(use->child)->invoke_show(arena, key, flags);
+ Inkscape::DrawingItem *ac = SP_ITEM(use->child)->invoke_show(drawing, key, flags);
if (ac) {
- nr_arena_item_add_child(ai, ac, NULL);
+ ai->prependChild(ac);
}
Geom::Translate t(use->x.computed,
use->y.computed);
- nr_arena_group_set_child_transform(NR_ARENA_GROUP(ai), Geom::Affine(t));
+ ai->setChildTransform(t);
}
return ai;
@@ -540,10 +540,10 @@ sp_use_href_changed(SPObject */*old_ref*/, SPObject */*ref*/, SPUse *use)
(use->child)->invoke_build(use->document, childrepr, TRUE);
for (SPItemView *v = item->display; v != NULL; v = v->next) {
- NRArenaItem *ai;
- ai = SP_ITEM(use->child)->invoke_show(NR_ARENA_ITEM_ARENA(v->arenaitem), v->key, v->flags);
+ Inkscape::DrawingItem *ai;
+ ai = SP_ITEM(use->child)->invoke_show(v->arenaitem->drawing(), v->key, v->flags);
if (ai) {
- nr_arena_item_add_child(v->arenaitem, ai, NULL);
+ v->arenaitem->prependChild(ai);
}
}
@@ -592,7 +592,8 @@ sp_use_update(SPObject *object, SPCtx *ctx, unsigned flags)
if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) {
for (SPItemView *v = SP_ITEM(object)->display; v != NULL; v = v->next) {
- nr_arena_group_set_style(NR_ARENA_GROUP(v->arenaitem), object->style);
+ Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem);
+ g->setStyle(object->style);
}
}
@@ -633,8 +634,9 @@ sp_use_update(SPObject *object, SPCtx *ctx, unsigned flags)
/* As last step set additional transform of arena group */
for (SPItemView *v = item->display; v != NULL; v = v->next) {
+ Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem);
Geom::Affine t(Geom::Translate(use->x.computed, use->y.computed));
- nr_arena_group_set_child_transform(NR_ARENA_GROUP(v->arenaitem), t);
+ g->setChildTransform(t);
}
}
@@ -650,7 +652,8 @@ sp_use_modified(SPObject *object, guint flags)
if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) {
for (SPItemView *v = SP_ITEM(object)->display; v != NULL; v = v->next) {
- nr_arena_group_set_style(NR_ARENA_GROUP(v->arenaitem), object->style);
+ Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem);
+ g->setStyle(object->style);
}
}
diff --git a/src/svg-view.cpp b/src/svg-view.cpp
index 2f1a20b82..8773dfab7 100644
--- a/src/svg-view.cpp
+++ b/src/svg-view.cpp
@@ -15,6 +15,7 @@
#include <2geom/transforms.h>
#include "display/canvas-arena.h"
+#include "display/drawing-group.h"
#include "document.h"
#include "sp-item.h"
#include "svg-view.h"
@@ -129,13 +130,13 @@ SPSVGView::mouseout()
*/
/// \todo fixme.
static gint
-arena_handler (SPCanvasArena */*arena*/, NRArenaItem *ai, GdkEvent *event, SPSVGView *svgview)
+arena_handler (SPCanvasArena */*arena*/, Inkscape::DrawingItem *ai, GdkEvent *event, SPSVGView *svgview)
{
static gdouble x, y;
static gboolean active = FALSE;
SPEvent spev;
- SPItem *spitem = (ai) ? (SPItem*)NR_ARENA_ITEM_GET_DATA (ai) : 0;
+ SPItem *spitem = (ai) ? (SPItem*) ai->data() : 0;
switch (event->type) {
case GDK_BUTTON_PRESS:
@@ -202,13 +203,13 @@ SPSVGView::setDocument (SPDocument *document)
View::setDocument (document);
if (document) {
- NRArenaItem *ai = document->getRoot()->invoke_show(
- SP_CANVAS_ARENA (_drawing)->arena,
+ Inkscape::DrawingItem *ai = document->getRoot()->invoke_show(
+ SP_CANVAS_ARENA (_drawing)->drawing,
_dkey,
SP_ITEM_SHOW_DISPLAY);
if (ai) {
- nr_arena_item_add_child (SP_CANVAS_ARENA (_drawing)->root, ai, NULL);
+ SP_CANVAS_ARENA (_drawing)->drawing.root()->prependChild(ai);
}
doRescale (!_rescale);
diff --git a/src/text-context.h b/src/text-context.h
index a140c2f08..50a738ca0 100644
--- a/src/text-context.h
+++ b/src/text-context.h
@@ -31,7 +31,6 @@
class SPTextContext;
class SPTextContextClass;
-class SPCanvasArena;
struct SPTextContext : public SPEventContext {
diff --git a/src/trace/trace.cpp b/src/trace/trace.cpp
index 813f532a4..7c47dc442 100644
--- a/src/trace/trace.cpp
+++ b/src/trace/trace.cpp
@@ -12,8 +12,6 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-
-
#include "trace/potrace/inkscape-potrace.h"
#include "inkscape.h"
@@ -31,23 +29,14 @@
#include "sp-image.h"
#include <2geom/transforms.h>
-#include "display/nr-arena.h"
-#include "display/nr-arena-shape.h"
+#include "display/drawing.h"
+#include "display/drawing-shape.h"
#include "siox.h"
#include "imagemap-gdk.h"
-
-
-namespace Inkscape
-{
-
-namespace Trace
-{
-
-
-
-
+namespace Inkscape {
+namespace Trace {
/**
* Get the selected image. Also check for any SPItems over it, in
@@ -247,25 +236,25 @@ Tracer::sioxProcessImage(SPImage *img,
return Glib::RefPtr<Gdk::Pixbuf>(NULL);
}
- NRArenaItem *aImg = img->get_arenaitem(desktop->dkey);
+ Inkscape::DrawingItem *aImg = img->get_arenaitem(desktop->dkey);
//g_message("img: %d %d %d %d\n", aImg->bbox.x0, aImg->bbox.y0,
// aImg->bbox.x1, aImg->bbox.y1);
- double width = (double)(aImg->bbox.x1 - aImg->bbox.x0);
- double height = (double)(aImg->bbox.y1 - aImg->bbox.y0);
+ double width = aImg->geometricBounds()->width();
+ double height = aImg->geometricBounds()->height();
- double iwidth = (double)simage.getWidth();
- double iheight = (double)simage.getHeight();
+ double iwidth = simage.getWidth();
+ double iheight = simage.getHeight();
double iwscale = width / iwidth;
double ihscale = height / iheight;
- std::vector<NRArenaItem *> arenaItems;
+ std::vector<Inkscape::DrawingItem *> arenaItems;
std::vector<SPShape *>::iterator iter;
for (iter = sioxShapes.begin() ; iter!=sioxShapes.end() ; iter++)
{
SPItem *item = *iter;
- NRArenaItem *aItem = item->get_arenaitem(desktop->dkey);
+ Inkscape::DrawingItem *aItem = item->get_arenaitem(desktop->dkey);
arenaItems.push_back(aItem);
}
@@ -278,25 +267,22 @@ Tracer::sioxProcessImage(SPImage *img,
for (int row=0 ; row<iheight ; row++)
{
- double ypos = ((double)aImg->bbox.y0) + ihscale * (double) row;
+ double ypos = aImg->geometricBounds()->top() + ihscale * (double) row;
for (int col=0 ; col<simage.getWidth() ; col++)
{
//Get absolute X,Y position
- double xpos = ((double)aImg->bbox.x0) + iwscale * (double)col;
+ double xpos = aImg->geometricBounds()->left() + iwscale * (double)col;
Geom::Point point(xpos, ypos);
- if (aImg->transform)
- point *= *aImg->transform;
+ point *= aImg->transform();
//point *= imgMat;
//point = desktop->doc2dt(point);
//g_message("x:%f y:%f\n", point[0], point[1]);
bool weHaveAHit = false;
- std::vector<NRArenaItem *>::iterator aIter;
+ std::vector<Inkscape::DrawingItem *>::iterator aIter;
for (aIter = arenaItems.begin() ; aIter!=arenaItems.end() ; aIter++)
{
- NRArenaItem *arenaItem = *aIter;
- NRArenaItemClass *arenaClass =
- (NRArenaItemClass *) NR_OBJECT_GET_CLASS (arenaItem);
- if (arenaClass->pick(arenaItem, point, 1.0f, 1))
+ Inkscape::DrawingItem *arenaItem = *aIter;
+ if (arenaItem->pick(point, 1.0f, 1))
{
weHaveAHit = true;
break;
@@ -338,17 +324,6 @@ Tracer::sioxProcessImage(SPImage *img,
//result.writePPM("siox2.ppm");
- /* Free Arena and ArenaItem */
- /*
- std::vector<NRArenaItem *>::iterator aIter;
- for (aIter = arenaItems.begin() ; aIter!=arenaItems.end() ; aIter++)
- {
- NRArenaItem *arenaItem = *aIter;
- nr_arena_item_unref(arenaItem);
- }
- nr_object_unref((NRObject *) arena);
- */
-
Glib::RefPtr<Gdk::Pixbuf> newPixbuf = Glib::wrap(result.getGdkPixbuf());
//g_message("siox: done");
diff --git a/src/ui/cache/svg_preview_cache.cpp b/src/ui/cache/svg_preview_cache.cpp
index cd1d65ba7..912bc1a40 100644
--- a/src/ui/cache/svg_preview_cache.cpp
+++ b/src/ui/cache/svg_preview_cache.cpp
@@ -27,54 +27,40 @@
#include "inkscape.h"
#include "sp-rect.h"
#include "document-private.h"
-#include "display/nr-arena.h"
-#include "display/nr-arena-item.h"
#include "display/cairo-utils.h"
+#include "display/drawing-context.h"
+#include "display/drawing-item.h"
+#include "display/drawing.h"
#include "ui/cache/svg_preview_cache.h"
-GdkPixbuf* render_pixbuf(NRArenaItem* root, double scale_factor, const Geom::Rect& dbox, unsigned psize) {
- NRGC gc(NULL);
-
+GdkPixbuf* render_pixbuf(Inkscape::Drawing &drawing, double scale_factor, const Geom::Rect& dbox, unsigned psize)
+{
Geom::Affine t(Geom::Scale(scale_factor, scale_factor));
- nr_arena_item_set_transform(root, t);
+ drawing.root()->setTransform(Geom::Scale(scale_factor));
- gc.transform.setIdentity();
- nr_arena_item_invoke_update( root, NULL, &gc,
- NR_ARENA_ITEM_STATE_ALL,
- NR_ARENA_ITEM_STATE_NONE );
+ Geom::IntRect ibox = (dbox * Geom::Scale(scale_factor)).roundOutwards();
- /* Item integer bbox in points */
- NRRectL ibox;
- ibox.x0 = floor(scale_factor * dbox.min()[Geom::X]);
- ibox.y0 = floor(scale_factor * dbox.min()[Geom::Y]);
- ibox.x1 = ceil(scale_factor * dbox.max()[Geom::X]);
- ibox.y1 = ceil(scale_factor * dbox.max()[Geom::Y]);
+ drawing.update(ibox);
/* Find visible area */
- int width = ibox.x1 - ibox.x0;
- int height = ibox.y1 - ibox.y0;
+ int width = ibox.width();
+ int height = ibox.height();
int dx = psize;
int dy = psize;
dx = (dx - width)/2; // watch out for size, since 'unsigned'-'signed' can cause problems if the result is negative
dy = (dy - height)/2;
- NRRectL area;
- area.x0 = ibox.x0 - dx;
- area.y0 = ibox.y0 - dy;
- area.x1 = area.x0 + psize;
- area.y1 = area.y0 + psize;
+ Geom::IntRect area = Geom::IntRect::from_xywh(
+ ibox.min() - Geom::IntPoint(dx, dy), Geom::IntPoint(psize, psize));
/* Render */
cairo_surface_t *s = cairo_image_surface_create(
CAIRO_FORMAT_ARGB32, psize, psize);
- cairo_t *ct = cairo_create(s);
- cairo_translate(ct, -area.x0, -area.y0);
+ Inkscape::DrawingContext ct(s, area.min());
- nr_arena_item_invoke_render(ct, root, &area, NULL,
- NR_ARENA_ITEM_RENDER_NO_CACHE );
+ drawing.render(ct, area, Inkscape::DrawingItem::RENDER_BYPASS_CACHE);
cairo_surface_flush(s);
- cairo_destroy(ct);
GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data(cairo_image_surface_get_data(s),
GDK_COLORSPACE_RGB,
@@ -120,7 +106,7 @@ void SvgPreview::set_preview_in_cache(const Glib::ustring& key, GdkPixbuf* px) {
_pixmap_cache[key] = px;
}
-GdkPixbuf* SvgPreview::get_preview(const gchar* uri, const gchar* id, NRArenaItem */*root*/,
+GdkPixbuf* SvgPreview::get_preview(const gchar* uri, const gchar* id, Inkscape::DrawingItem */*root*/,
double /*scale_factor*/, unsigned int psize) {
// First try looking up the cached preview in the cache map
Glib::ustring key = cache_key(uri, id, psize);
@@ -135,6 +121,17 @@ GdkPixbuf* SvgPreview::get_preview(const gchar* uri, const gchar* id, NRArenaIte
return px;
}
-};
-};
-};
+}
+}
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/cache/svg_preview_cache.h b/src/ui/cache/svg_preview_cache.h
index 0fac94782..2318307e2 100644
--- a/src/ui/cache/svg_preview_cache.h
+++ b/src/ui/cache/svg_preview_cache.h
@@ -1,17 +1,22 @@
-#ifndef __SVG_PREVIEW_CACHE_H__
-#define __SVG_PREVIEW_CACHE_H__
-
-/** \file
- * SPIcon: Generic icon widget
+/** @file
+ * @brief Preview cache
*/
/*
* Copyright (C) 2007 Bryce W. Harrington <bryce@bryceharrington.org>
- *
* Released under GNU GPL, read the file 'COPYING' for more information
- *
*/
-GdkPixbuf* render_pixbuf(NRArenaItem* root, double scale_factor, const Geom::Rect& dbox, unsigned psize);
+#ifndef SEEN_INKSCAPE_UI_SVG_PREVIEW_CACHE_H
+#define SEEN_INKSCAPE_UI_SVG_PREVIEW_CACHE_H
+
+#include <map>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <glibmm/ustring.h>
+#include <2geom/rect.h>
+
+#include "display/display-forward.h"
+
+GdkPixbuf* render_pixbuf(Inkscape::Drawing &drawing, double scale_factor, const Geom::Rect& dbox, unsigned psize);
namespace Inkscape {
namespace UI {
@@ -28,7 +33,7 @@ class SvgPreview {
Glib::ustring cache_key(gchar const *uri, gchar const *name, unsigned psize) const;
GdkPixbuf* get_preview_from_cache(const Glib::ustring& key);
void set_preview_in_cache(const Glib::ustring& key, GdkPixbuf* px);
- GdkPixbuf* get_preview(const gchar* uri, const gchar* id, NRArenaItem *root, double scale_factor, unsigned int psize);
+ GdkPixbuf* get_preview(const gchar* uri, const gchar* id, Inkscape::DrawingItem *root, double scale_factor, unsigned int psize);
};
}; // namespace Cache
diff --git a/src/ui/dialog/color-item.cpp b/src/ui/dialog/color-item.cpp
index 598827da9..b61925855 100644
--- a/src/ui/dialog/color-item.cpp
+++ b/src/ui/dialog/color-item.cpp
@@ -460,8 +460,8 @@ void ColorItem::_updatePreviews()
for ( std::vector<SwatchPage*>::iterator it2 = possible.begin(); it2 != possible.end() && !found; ++it2 ) {
SwatchPage* curr = *it2;
index = 0;
- for ( std::vector<ColorItem*>::iterator zz = curr->_colors.begin(); zz != curr->_colors.end(); ++zz ) {
- if ( this == *zz ) {
+ for ( boost::ptr_vector<ColorItem>::iterator zz = curr->_colors.begin(); zz != curr->_colors.end(); ++zz ) {
+ if ( this == &*zz ) {
found = true;
paletteName = curr->_name;
break;
@@ -734,12 +734,12 @@ void ColorItem::_wireMagicColors( SwatchPage *colorSet )
{
if ( colorSet )
{
- for ( std::vector<ColorItem*>::iterator it = colorSet->_colors.begin(); it != colorSet->_colors.end(); ++it )
+ for ( boost::ptr_vector<ColorItem>::iterator it = colorSet->_colors.begin(); it != colorSet->_colors.end(); ++it )
{
- std::string::size_type pos = (*it)->def.descr.find("*{");
+ std::string::size_type pos = it->def.descr.find("*{");
if ( pos != std::string::npos )
{
- std::string subby = (*it)->def.descr.substr( pos + 2 );
+ std::string subby = it->def.descr.substr( pos + 2 );
std::string::size_type endPos = subby.find("}*");
if ( endPos != std::string::npos )
{
@@ -749,12 +749,12 @@ void ColorItem::_wireMagicColors( SwatchPage *colorSet )
if ( subby.find('E') != std::string::npos )
{
- (*it)->def.setEditable( true );
+ it->def.setEditable( true );
}
if ( subby.find('L') != std::string::npos )
{
- (*it)->_isLive = true;
+ it->_isLive = true;
}
std::string part;
@@ -764,7 +764,7 @@ void ColorItem::_wireMagicColors( SwatchPage *colorSet )
if ( popVal( colorIndex, part ) ) {
guint64 percent = 0;
if ( popVal( percent, part ) ) {
- (*it)->_linkTint( *(colorSet->_colors[colorIndex]), percent );
+ it->_linkTint( colorSet->_colors[colorIndex], percent );
}
}
}
@@ -779,7 +779,7 @@ void ColorItem::_wireMagicColors( SwatchPage *colorSet )
if ( !popVal( grayLevel, part ) ) {
grayLevel = 0;
}
- (*it)->_linkTone( *(colorSet->_colors[colorIndex]), percent, grayLevel );
+ it->_linkTone( colorSet->_colors[colorIndex], percent, grayLevel );
}
}
}
diff --git a/src/ui/dialog/color-item.h b/src/ui/dialog/color-item.h
index 9080498eb..d06082f2e 100644
--- a/src/ui/dialog/color-item.h
+++ b/src/ui/dialog/color-item.h
@@ -12,6 +12,7 @@
#ifndef SEEN_DIALOGS_COLOR_ITEM_H
#define SEEN_DIALOGS_COLOR_ITEM_H
+#include <boost/ptr_container/ptr_vector.hpp>
#include <gtkmm/tooltips.h>
#include "widgets/ege-paint-def.h"
@@ -33,7 +34,7 @@ public:
Glib::ustring _name;
int _prefWidth;
- std::vector<ColorItem*> _colors;
+ boost::ptr_vector<ColorItem> _colors;
};
diff --git a/src/ui/dialog/filedialogimpl-win32.cpp b/src/ui/dialog/filedialogimpl-win32.cpp
index bb800f9ca..4f4093a99 100644
--- a/src/ui/dialog/filedialogimpl-win32.cpp
+++ b/src/ui/dialog/filedialogimpl-win32.cpp
@@ -34,8 +34,8 @@
#include "extension/output.h"
#include "extension/db.h"
-#include "display/nr-arena-item.h"
-#include "display/nr-arena.h"
+//#include "display/drawing-item.h"
+//#include "display/drawing.h"
#include "sp-item.h"
#include "display/canvas-arena.h"
diff --git a/src/ui/dialog/icon-preview.cpp b/src/ui/dialog/icon-preview.cpp
index 38ec6d1be..9865c0cdb 100644
--- a/src/ui/dialog/icon-preview.cpp
+++ b/src/ui/dialog/icon-preview.cpp
@@ -16,6 +16,7 @@
# include <config.h>
#endif
+#include <boost/scoped_ptr.hpp>
#include <gtk/gtk.h>
#include <glib/gmem.h>
#include <glibmm/i18n.h>
@@ -25,7 +26,7 @@
#include "desktop.h"
#include "desktop-handles.h"
-#include "display/nr-arena.h"
+#include "display/drawing.h"
#include "document.h"
#include "inkscape.h"
#include "preferences.h"
@@ -36,9 +37,10 @@
#include "icon-preview.h"
extern "C" {
-// takes doc, root, icon, and icon name to produce pixels
+// takes doc, drawing, icon, and icon name to produce pixels
+// this is defined in widgets/icon.cpp
guchar *
-sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root,
+sp_icon_doc_icon( SPDocument *doc, Inkscape::Drawing &drawing,
const gchar *name, unsigned int psize, unsigned &stride);
}
@@ -438,20 +440,16 @@ void IconPreviewPanel::renderPreview( SPObject* obj )
g_message("%s setting up to render '%s' as the icon", getTimestr().c_str(), id );
#endif // ICON_VERBOSE
- NRArenaItem *root = NULL;
+ Inkscape::Drawing drawing;
- /* Create new arena */
- NRArena *arena = NRArena::create();
-
- /* Create ArenaItem and set transform */
+ /* Create drawing items and set transform */
unsigned int visionkey = SPItem::display_key_new(1);
-
- root = doc->getRoot()->invoke_show( arena, visionkey, SP_ITEM_SHOW_DISPLAY );
+ drawing.setRoot(doc->getRoot()->invoke_show( drawing, visionkey, SP_ITEM_SHOW_DISPLAY ));
for ( int i = 0; i < numEntries; i++ ) {
unsigned unused;
int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, sizes[i]);
- guchar * px = sp_icon_doc_icon( doc, root, id, sizes[i], unused);
+ guchar * px = sp_icon_doc_icon( doc, drawing, id, sizes[i], unused);
// g_message( " size %d %s", sizes[i], (px ? "worked" : "failed") );
if ( px ) {
memcpy( pixMem[i], px, sizes[i] * stride );
@@ -465,7 +463,6 @@ void IconPreviewPanel::renderPreview( SPObject* obj )
updateMagnify();
doc->getRoot()->invoke_hide(visionkey);
- nr_object_unref((NRObject *) arena);
renderTimer->stop();
minDelay = std::max( 0.1, renderTimer->elapsed() * 3.0 );
#if ICON_VERBOSE
diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp
index d11ffd565..ae27f0720 100644
--- a/src/ui/dialog/inkscape-preferences.cpp
+++ b/src/ui/dialog/inkscape-preferences.cpp
@@ -124,7 +124,7 @@ InkscapePreferences::InkscapePreferences()
initPageTransforms();
initPageClones();
initPageMasks();
- initPageFilters();
+ initPageRendering();
initPageBitmaps();
initPageCMS();
initPageGrids();
@@ -739,8 +739,22 @@ void InkscapePreferences::initPageTransforms()
this->AddPage(_page_transforms, _("Transforms"), PREFS_PAGE_TRANSFORMS);
}
-void InkscapePreferences::initPageFilters()
+void InkscapePreferences::initPageRendering()
{
+ /* show infobox */
+ _show_filters_info_box.init( _("Show filter primitives infobox"), "/options/showfiltersinfobox/value", true);
+ _page_rendering.add_line(true, "", _show_filters_info_box, "",
+ _("Show icons and descriptions for the filter primitives available at the filter effects dialog"));
+
+ /* threaded blur */ //related comments/widgets/functions should be renamed and option should be moved elsewhere when inkscape is fully multi-threaded
+ _filter_multi_threaded.init("/options/threading/numthreads", 1.0, 8.0, 1.0, 2.0, 4.0, true, false);
+ _page_rendering.add_line( false, _("Number of Threads:"), _filter_multi_threaded, _("(requires restart)"),
+ _("Configure number of processors/threads to use when rendering filters"), false);
+
+ // rendering cache
+ _rendering_cache_size.init("/options/renderingcache/size", 0.0, 4096.0, 1.0, 32.0, 64.0, true, false);
+ _page_rendering.add_line( false, _("Rendering cache size:"), _rendering_cache_size, C_("mebibyte (2^20 bytes) abbreviation","MiB"), _("Set the amount of memory per document which can be used to store rendered parts of the drawing for later reuse; set to zero to disable caching"), false);
+
/* blur quality */
_blur_quality_best.init ( _("Best quality (slowest)"), "/options/blurquality/value",
BLUR_QUALITY_BEST, false, 0);
@@ -753,16 +767,16 @@ void InkscapePreferences::initPageFilters()
_blur_quality_worst.init ( _("Lowest quality (fastest)"), "/options/blurquality/value",
BLUR_QUALITY_WORST, false, &_blur_quality_best);
- _page_filters.add_group_header( _("Gaussian blur quality for display"));
- _page_filters.add_line( true, "", _blur_quality_best, "",
+ _page_rendering.add_group_header( _("Gaussian blur quality for display"));
+ _page_rendering.add_line( true, "", _blur_quality_best, "",
_("Best quality, but display may be very slow at high zooms (bitmap export always uses best quality)"));
- _page_filters.add_line( true, "", _blur_quality_better, "",
+ _page_rendering.add_line( true, "", _blur_quality_better, "",
_("Better quality, but slower display"));
- _page_filters.add_line( true, "", _blur_quality_normal, "",
+ _page_rendering.add_line( true, "", _blur_quality_normal, "",
_("Average quality, acceptable display speed"));
- _page_filters.add_line( true, "", _blur_quality_worse, "",
+ _page_rendering.add_line( true, "", _blur_quality_worse, "",
_("Lower quality (some artifacts), but display is faster"));
- _page_filters.add_line( true, "", _blur_quality_worst, "",
+ _page_rendering.add_line( true, "", _blur_quality_worst, "",
_("Lowest quality (considerable artifacts), but display is fastest"));
/* filter quality */
@@ -777,29 +791,19 @@ void InkscapePreferences::initPageFilters()
_filter_quality_worst.init ( _("Lowest quality (fastest)"), "/options/filterquality/value",
Inkscape::Filters::FILTER_QUALITY_WORST, false, &_filter_quality_best);
- _page_filters.add_group_header( _("Filter effects quality for display"));
- _page_filters.add_line( true, "", _filter_quality_best, "",
+ _page_rendering.add_group_header( _("Filter effects quality for display"));
+ _page_rendering.add_line( true, "", _filter_quality_best, "",
_("Best quality, but display may be very slow at high zooms (bitmap export always uses best quality)"));
- _page_filters.add_line( true, "", _filter_quality_better, "",
+ _page_rendering.add_line( true, "", _filter_quality_better, "",
_("Better quality, but slower display"));
- _page_filters.add_line( true, "", _filter_quality_normal, "",
+ _page_rendering.add_line( true, "", _filter_quality_normal, "",
_("Average quality, acceptable display speed"));
- _page_filters.add_line( true, "", _filter_quality_worse, "",
+ _page_rendering.add_line( true, "", _filter_quality_worse, "",
_("Lower quality (some artifacts), but display is faster"));
- _page_filters.add_line( true, "", _filter_quality_worst, "",
+ _page_rendering.add_line( true, "", _filter_quality_worst, "",
_("Lowest quality (considerable artifacts), but display is fastest"));
- /* show infobox */
- _show_filters_info_box.init( _("Show filter primitives infobox"), "/options/showfiltersinfobox/value", true);
- _page_filters.add_line(true, "", _show_filters_info_box, "",
- _("Show icons and descriptions for the filter primitives available at the filter effects dialog"));
-
- /* threaded blur */ //related comments/widgets/functions should be renamed and option should be moved elsewhere when inkscape is fully multi-threaded
- _filter_multi_threaded.init("/options/threading/numthreads", 1.0, 8.0, 1.0, 2.0, 4.0, true, false);
- _page_filters.add_line( false, _("Number of Threads:"), _filter_multi_threaded, _("(requires restart)"),
- _("Configure number of processors/threads to use with rendering of gaussian blur"), false);
-
- this->AddPage(_page_filters, _("Filters"), PREFS_PAGE_FILTERS);
+ this->AddPage(_page_rendering, _("Rendering"), PREFS_PAGE_RENDERING);
}
diff --git a/src/ui/dialog/inkscape-preferences.h b/src/ui/dialog/inkscape-preferences.h
index 13851e525..d783a2df1 100644
--- a/src/ui/dialog/inkscape-preferences.h
+++ b/src/ui/dialog/inkscape-preferences.h
@@ -44,7 +44,7 @@ enum {
PREFS_PAGE_TOOLS_SELECTOR,
PREFS_PAGE_TOOLS_NODE,
PREFS_PAGE_TOOLS_TWEAK,
- PREFS_PAGE_TOOLS_SPRAY,
+ PREFS_PAGE_TOOLS_SPRAY,
PREFS_PAGE_TOOLS_ZOOM,
PREFS_PAGE_TOOLS_MEASURE,
PREFS_PAGE_TOOLS_SHAPES,
@@ -67,7 +67,7 @@ enum {
PREFS_PAGE_TRANSFORMS,
PREFS_PAGE_CLONES,
PREFS_PAGE_MASKS,
- PREFS_PAGE_FILTERS,
+ PREFS_PAGE_RENDERING,
PREFS_PAGE_BITMAPS,
PREFS_PAGE_CMS,
PREFS_PAGE_GRIDS,
@@ -124,7 +124,7 @@ protected:
UI::Widget::DialogPage _page_clones;
UI::Widget::DialogPage _page_mask;
UI::Widget::DialogPage _page_transforms;
- UI::Widget::DialogPage _page_filters;
+ UI::Widget::DialogPage _page_rendering;
UI::Widget::DialogPage _page_select;
UI::Widget::DialogPage _page_importexport;
UI::Widget::DialogPage _page_cms;
@@ -254,6 +254,7 @@ protected:
UI::Widget::PrefRadioButton _filter_quality_worse;
UI::Widget::PrefRadioButton _filter_quality_worst;
UI::Widget::PrefCheckButton _show_filters_info_box;
+ UI::Widget::PrefSpinButton _rendering_cache_size;
UI::Widget::PrefSpinButton _filter_multi_threaded;
UI::Widget::PrefCheckButton _trans_scale_stroke;
@@ -389,7 +390,7 @@ protected:
void initPageClones();
void initPageMasks();
void initPageTransforms();
- void initPageFilters();
+ void initPageRendering();
void initPageSelecting();
void initPageImportExport();
void initPageCMS();
diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp
index ad3b79630..910d63873 100644
--- a/src/ui/dialog/swatches.cpp
+++ b/src/ui/dialog/swatches.cpp
@@ -885,7 +885,7 @@ void SwatchesPanel::_setDocument( SPDocument *document )
}
static void recalcSwatchContents(SPDocument* doc,
- std::vector<ColorItem*> &tmpColors,
+ boost::ptr_vector<ColorItem> &tmpColors,
std::map<ColorItem*, cairo_pattern_t*> &previewMappings,
std::map<ColorItem*, SPGradient*> &gradMappings)
{
@@ -938,7 +938,7 @@ void SwatchesPanel::handleGradientsChange(SPDocument *document)
{
SwatchPage *docPalette = (docPalettes.find(document) != docPalettes.end()) ? docPalettes[document] : 0;
if (docPalette) {
- std::vector<ColorItem*> tmpColors;
+ boost::ptr_vector<ColorItem> tmpColors;
std::map<ColorItem*, cairo_pattern_t*> tmpPrevs;
std::map<ColorItem*, SPGradient*> tmpGrads;
recalcSwatchContents(document, tmpColors, tmpPrevs, tmpGrads);
@@ -953,9 +953,6 @@ void SwatchesPanel::handleGradientsChange(SPDocument *document)
}
docPalette->_colors.swap(tmpColors);
- for (std::vector<ColorItem*>::iterator it = tmpColors.begin(); it != tmpColors.end(); ++it) {
- delete *it;
- }
// Figure out which SwatchesPanel instances are affected and update them.
@@ -976,7 +973,7 @@ void SwatchesPanel::handleDefsModified(SPDocument *document)
{
SwatchPage *docPalette = (docPalettes.find(document) != docPalettes.end()) ? docPalettes[document] : 0;
if (docPalette && !DocTrack::queueUpdateIfNeeded(document) ) {
- std::vector<ColorItem*> tmpColors;
+ boost::ptr_vector<ColorItem> tmpColors;
std::map<ColorItem*, cairo_pattern_t*> tmpPrevs;
std::map<ColorItem*, SPGradient*> tmpGrads;
recalcSwatchContents(document, tmpColors, tmpPrevs, tmpGrads);
@@ -986,8 +983,8 @@ void SwatchesPanel::handleDefsModified(SPDocument *document)
} else {
int cap = std::min(docPalette->_colors.size(), tmpColors.size());
for (int i = 0; i < cap; i++) {
- ColorItem* newColor = tmpColors[i];
- ColorItem* oldColor = docPalette->_colors[i];
+ ColorItem *newColor = &tmpColors[i];
+ ColorItem *oldColor = &docPalette->_colors[i];
if ( (newColor->def.getType() != oldColor->def.getType()) ||
(newColor->def.getR() != oldColor->def.getR()) ||
(newColor->def.getG() != oldColor->def.getG()) ||
@@ -1006,9 +1003,6 @@ void SwatchesPanel::handleDefsModified(SPDocument *document)
for (std::map<ColorItem*, cairo_pattern_t*>::iterator it = tmpPrevs.begin(); it != tmpPrevs.end(); ++it) {
cairo_pattern_destroy(it->second);
}
- for (std::vector<ColorItem*>::iterator it = tmpColors.begin(); it != tmpColors.end(); ++it) {
- delete *it;
- }
}
}
@@ -1098,8 +1092,8 @@ void SwatchesPanel::_updateFromSelection()
}
sp_style_unref(tmpStyle);
- for ( std::vector<ColorItem*>::iterator it = docPalette->_colors.begin(); it != docPalette->_colors.end(); ++it ) {
- ColorItem* item = *it;
+ for ( boost::ptr_vector<ColorItem>::iterator it = docPalette->_colors.begin(); it != docPalette->_colors.end(); ++it ) {
+ ColorItem* item = &*it;
bool isFill = (fillId == item->def.descr);
bool isStroke = (strokeId == item->def.descr);
item->setState( isFill, isStroke );
@@ -1140,8 +1134,8 @@ void SwatchesPanel::_rebuild()
_holder->freezeUpdates();
// TODO restore once 'clear' works _holder->addPreview(_clear);
_holder->addPreview(_remove);
- for ( std::vector<ColorItem*>::iterator it = curr->_colors.begin(); it != curr->_colors.end(); it++ ) {
- _holder->addPreview(*it);
+ for ( boost::ptr_vector<ColorItem>::iterator it = curr->_colors.begin(); it != curr->_colors.end(); it++ ) {
+ _holder->addPreview(&*it);
}
_holder->thawUpdates();
}
diff --git a/src/ui/view/view.h b/src/ui/view/view.h
index 13499a2e4..db6061434 100644
--- a/src/ui/view/view.h
+++ b/src/ui/view/view.h
@@ -65,7 +65,7 @@ namespace Inkscape {
/**
* View is an abstract base class of all UI document views. This
* includes both the editing window and the SVG preview, but does not
- * include the non-UI RGBA buffer-based NRArena nor the XML editor or
+ * include the non-UI RGBA buffer-based Inkscape::Drawing nor the XML editor or
* similar views. The View base class has very little functionality of
* its own.
*/
diff --git a/src/widgets/desktop-widget.cpp b/src/widgets/desktop-widget.cpp
index 7958a9d07..08f0eadfb 100644
--- a/src/widgets/desktop-widget.cpp
+++ b/src/widgets/desktop-widget.cpp
@@ -36,7 +36,6 @@
#include "desktop-widget.h"
#include "display/sp-canvas.h"
#include "display/canvas-arena.h"
-#include "display/nr-arena.h"
#include "document.h"
#include "ege-color-prof-tracker.h"
#include "ege-select-one-action.h"
@@ -641,10 +640,10 @@ SPDesktopWidget::updateTitle(gchar const* uri)
gchar const *colormodename = "";
gchar const *colormodenamecomma = "";
- if (this->desktop->getColorMode() == Inkscape::COLORRENDERMODE_GRAYSCALE) {
+ if (this->desktop->getColorMode() == Inkscape::COLORMODE_GRAYSCALE) {
colormodename = grayscalename;
colormodenamecomma = grayscalenamecomma;
- } else if (this->desktop->getColorMode() == Inkscape::COLORRENDERMODE_PRINT_COLORS_PREVIEW) {
+ } else if (this->desktop->getColorMode() == Inkscape::COLORMODE_PRINT_COLORS_PREVIEW) {
colormodename = printcolorsname;
colormodenamecomma = printcolorsnamecomma;
}
diff --git a/src/widgets/icon.cpp b/src/widgets/icon.cpp
index 6110e6011..a57b56b5c 100644
--- a/src/widgets/icon.cpp
+++ b/src/widgets/icon.cpp
@@ -31,8 +31,9 @@
#include "document.h"
#include "sp-item.h"
#include "display/cairo-utils.h"
-#include "display/nr-arena.h"
-#include "display/nr-arena-item.h"
+#include "display/drawing-context.h"
+#include "display/drawing-item.h"
+#include "display/drawing.h"
#include "io/sys.h"
#include "sp-root.h"
@@ -1074,9 +1075,22 @@ GdkPixbuf *IconImpl::loadPixmap(gchar const *name, unsigned /*lsize*/, unsigned
return pb;
}
-// takes doc, root, icon, and icon name to produce pixels
+static Geom::IntRect round_rect(Geom::Rect const &r)
+{
+ using Geom::X;
+ using Geom::Y;
+ Geom::IntPoint a, b;
+ a[X] = round(r.left());
+ a[Y] = round(r.top());
+ b[X] = round(r.right());
+ b[Y] = round(r.bottom());
+ Geom::IntRect ret(a, b);
+ return ret;
+}
+
+// takes doc, drawing, icon, and icon name to produce pixels
extern "C" guchar *
-sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root,
+sp_icon_doc_icon( SPDocument *doc, Inkscape::Drawing &drawing,
gchar const *name, unsigned psize,
unsigned &stride)
{
@@ -1099,28 +1113,21 @@ sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root,
/* This is in document coordinates, i.e. pixels */
if ( dbox ) {
- NRGC gc(NULL);
/* Update to renderable state */
double sf = 1.0;
- nr_arena_item_set_transform(root, (Geom::Affine)Geom::Scale(sf, sf));
- gc.transform.setIdentity();
- nr_arena_item_invoke_update( root, NULL, &gc,
- NR_ARENA_ITEM_STATE_ALL,
- NR_ARENA_ITEM_STATE_NONE );
+ drawing.root()->setTransform(Geom::Scale(sf));
+ drawing.update();
/* Item integer bbox in points */
- NRRectL ibox;
- ibox.x0 = (int) floor(sf * dbox->min()[Geom::X] + 0.5);
- ibox.y0 = (int) floor(sf * dbox->min()[Geom::Y] + 0.5);
- ibox.x1 = (int) floor(sf * dbox->max()[Geom::X] + 0.5);
- ibox.y1 = (int) floor(sf * dbox->max()[Geom::Y] + 0.5);
+ // NOTE: previously, each rect coordinate was rounded using floor(c + 0.5)
+ Geom::IntRect ibox = round_rect(*dbox);
if ( dump ) {
- g_message( " box --'%s' (%f,%f)-(%f,%f)", name, (double)ibox.x0, (double)ibox.y0, (double)ibox.x1, (double)ibox.y1 );
+ g_message( " box --'%s' (%f,%f)-(%f,%f)", name, (double)ibox.left(), (double)ibox.top(), (double)ibox.right(), (double)ibox.bottom() );
}
/* Find button visible area */
- int width = ibox.x1 - ibox.x0;
- int height = ibox.y1 - ibox.y0;
+ int width = ibox.width();
+ int height = ibox.height();
if ( dump ) {
g_message( " vis --'%s' (%d,%d)", name, width, height );
@@ -1134,51 +1141,37 @@ sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root,
}
sf = (double)psize / (double)block;
- nr_arena_item_set_transform(root, (Geom::Affine)Geom::Scale(sf, sf));
- gc.transform.setIdentity();
- nr_arena_item_invoke_update( root, NULL, &gc,
- NR_ARENA_ITEM_STATE_ALL,
- NR_ARENA_ITEM_STATE_NONE );
- /* Item integer bbox in points */
- ibox.x0 = (int) floor(sf * dbox->min()[Geom::X] + 0.5);
- ibox.y0 = (int) floor(sf * dbox->min()[Geom::Y] + 0.5);
- ibox.x1 = (int) floor(sf * dbox->max()[Geom::X] + 0.5);
- ibox.y1 = (int) floor(sf * dbox->max()[Geom::Y] + 0.5);
+ drawing.root()->setTransform(Geom::Scale(sf));
+ drawing.update();
+ ibox = round_rect(*dbox * Geom::Scale(sf));
if ( dump ) {
- g_message( " box2 --'%s' (%f,%f)-(%f,%f)", name, (double)ibox.x0, (double)ibox.y0, (double)ibox.x1, (double)ibox.y1 );
+ g_message( " box2 --'%s' (%f,%f)-(%f,%f)", name, (double)ibox.left(), (double)ibox.top(), (double)ibox.right(), (double)ibox.bottom() );
}
/* Find button visible area */
- width = ibox.x1 - ibox.x0;
- height = ibox.y1 - ibox.y0;
+ width = ibox.width();
+ height = ibox.height();
if ( dump ) {
g_message( " vis2 --'%s' (%d,%d)", name, width, height );
}
}
}
+ Geom::IntPoint pdim(psize, psize);
int dx, dy;
//dx = (psize - width) / 2;
//dy = (psize - height) / 2;
dx=dy=psize;
dx=(dx-width)/2; // watch out for psize, since 'unsigned'-'signed' can cause problems if the result is negative
dy=(dy-height)/2;
- NRRectL area;
- area.x0 = ibox.x0 - dx;
- area.y0 = ibox.y0 - dy;
- area.x1 = area.x0 + psize;
- area.y1 = area.y0 + psize;
+ Geom::IntRect area = Geom::IntRect::from_xywh(ibox.min() - Geom::IntPoint(dx,dy), pdim);
/* Actual renderable area */
- NRRectL ua;
- ua.x0 = MAX(ibox.x0, area.x0);
- ua.y0 = MAX(ibox.y0, area.y0);
- ua.x1 = MIN(ibox.x1, area.x1);
- ua.y1 = MIN(ibox.y1, area.y1);
+ Geom::IntRect ua = *Geom::intersect(ibox, area);
if ( dump ) {
- g_message( " area --'%s' (%f,%f)-(%f,%f)", name, (double)area.x0, (double)area.y0, (double)area.x1, (double)area.y1 );
- g_message( " ua --'%s' (%f,%f)-(%f,%f)", name, (double)ua.x0, (double)ua.y0, (double)ua.x1, (double)ua.y1 );
+ g_message( " area --'%s' (%f,%f)-(%f,%f)", name, (double)area.left(), (double)area.top(), (double)area.right(), (double)area.bottom() );
+ g_message( " ua --'%s' (%f,%f)-(%f,%f)", name, (double)ua.left(), (double)ua.top(), (double)ua.right(), (double)ua.bottom() );
}
stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, psize);
@@ -1190,12 +1183,9 @@ sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root,
/* Render */
cairo_surface_t *s = cairo_image_surface_create_for_data(px,
CAIRO_FORMAT_ARGB32, psize, psize, stride);
- cairo_t *ct = cairo_create(s);
- cairo_translate(ct, -ua.x0, -ua.y0);
+ Inkscape::DrawingContext ct(s, ua.min());
- nr_arena_item_invoke_render(ct, root, &ua, NULL,
- NR_ARENA_ITEM_RENDER_NO_CACHE );
- cairo_destroy(ct);
+ drawing.render(ct, ua);
cairo_surface_destroy(s);
// convert to GdkPixbuf format
@@ -1216,9 +1206,21 @@ sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root,
class SVGDocCache
{
public:
- SVGDocCache( SPDocument *doc, NRArenaItem *root ) : doc(doc), root(root) {}
+ SVGDocCache( SPDocument *doc )
+ : doc(doc)
+ , visionkey(SPItem::display_key_new(1))
+ {
+ doc->doRef();
+ doc->ensureUpToDate();
+ drawing.setRoot(doc->getRoot()->invoke_show(drawing, visionkey, SP_ITEM_SHOW_DISPLAY ));
+ }
+ ~SVGDocCache() {
+ doc->getRoot()->invoke_hide(visionkey);
+ doc->doUnref();
+ }
SPDocument *doc;
- NRArenaItem *root;
+ Inkscape::Drawing drawing;
+ unsigned visionkey;
};
static std::map<Glib::ustring, SVGDocCache *> doc_cache;
@@ -1285,27 +1287,14 @@ guchar *IconImpl::load_svg_pixels(std::list<Glib::ustring> const &names,
if ( dump ) {
g_message("Loaded icon file %s", doc_filename);
}
- // prep the document
- doc->ensureUpToDate();
-
- // Create new arena
- NRArena *arena = NRArena::create();
-
- // Create ArenaItem and set transform
- unsigned visionkey = SPItem::display_key_new(1);
- // fixme: Memory manage root if needed (Lauris)
- // This needs to be fixed indeed; this leads to a memory leak of a few megabytes these days
- // because shapes are being rendered which are not being freed
- NRArenaItem *root = doc->getRoot()->invoke_show( arena, visionkey, SP_ITEM_SHOW_DISPLAY );
-
// store into the cache
- info = new SVGDocCache(doc, root);
+ info = new SVGDocCache(doc);
doc_cache[key] = info;
}
}
if (info) {
for (std::list<Glib::ustring>::const_iterator it = names.begin(); !px && (it != names.end()); ++it ) {
- px = sp_icon_doc_icon( info->doc, info->root, it->c_str(), psize, stride );
+ px = sp_icon_doc_icon( info->doc, info->drawing, it->c_str(), psize, stride );
}
}
}
diff --git a/src/widgets/stroke-style.cpp b/src/widgets/stroke-style.cpp
index 8b5582163..8d9b9b429 100644
--- a/src/widgets/stroke-style.cpp
+++ b/src/widgets/stroke-style.cpp
@@ -28,8 +28,8 @@
#include "desktop-style.h"
#include "dialogs/dialog-events.h"
#include "display/canvas-bpath.h" // for SP_STROKE_LINEJOIN_*
-#include "display/nr-arena.h"
-#include "display/nr-arena-item.h"
+#include "display/display-forward.h"
+#include "display/drawing.h"
#include "document-private.h"
#include "gradient-chemistry.h"
#include "helper/stock-items.h"
@@ -153,7 +153,7 @@ sp_stroke_radio_button(Gtk::RadioButton *tb, char const *icon,
static Gtk::Image *
sp_marker_prev_new(unsigned psize, gchar const *mname,
SPDocument *source, SPDocument *sandbox,
- gchar const *menu_id, NRArena const * /*arena*/, unsigned /*visionkey*/, NRArenaItem *root)
+ gchar const *menu_id, Inkscape::Drawing &drawing, unsigned /*visionkey*/)
{
// Retrieve the marker named 'mname' from the source SVG document
SPObject const *marker = source->getObjectById(mname);
@@ -208,7 +208,7 @@ sp_marker_prev_new(unsigned psize, gchar const *mname,
Glib::RefPtr<Gdk::Pixbuf> pixbuf = Glib::wrap(svg_preview_cache.get_preview_from_cache(key));
if (!pixbuf) {
- pixbuf = Glib::wrap(render_pixbuf(root, sf, *dbox, psize));
+ pixbuf = Glib::wrap(render_pixbuf(drawing, sf, *dbox, psize));
svg_preview_cache.set_preview_in_cache(key, pixbuf->gobj());
}
@@ -248,9 +248,9 @@ static void
sp_marker_menu_build (Gtk::Menu *m, GSList *marker_list, SPDocument *source, SPDocument *sandbox, gchar const *menu_id)
{
// Do this here, outside of loop, to speed up preview generation:
- NRArena const *arena = NRArena::create();
+ Inkscape::Drawing drawing;
unsigned const visionkey = SPItem::display_key_new(1);
- NRArenaItem *root = sandbox->getRoot()->invoke_show((NRArena *) arena, visionkey, SP_ITEM_SHOW_DISPLAY);
+ drawing.setRoot(sandbox->getRoot()->invoke_show(drawing, visionkey, SP_ITEM_SHOW_DISPLAY));
for (; marker_list != NULL; marker_list = marker_list->next) {
Inkscape::XML::Node *repr = reinterpret_cast<SPItem *>(marker_list->data)->getRepr();
@@ -271,7 +271,7 @@ sp_marker_menu_build (Gtk::Menu *m, GSList *marker_list, SPDocument *source, SPD
// generate preview
- Gtk::Image *prv = sp_marker_prev_new (22, markid, source, sandbox, menu_id, arena, visionkey, root);
+ Gtk::Image *prv = sp_marker_prev_new (22, markid, source, sandbox, menu_id, drawing, visionkey);
prv->show();
hb->pack_start(*prv, false, false, 6);
@@ -289,7 +289,6 @@ sp_marker_menu_build (Gtk::Menu *m, GSList *marker_list, SPDocument *source, SPD
}
sandbox->getRoot()->invoke_hide(visionkey);
- nr_object_unref((NRObject *) arena);
}
/**