summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorNiko Kiirala <niko@kiirala.com>2007-12-06 23:31:29 +0000
committerkiirala <kiirala@users.sourceforge.net>2007-12-06 23:31:29 +0000
commita26ea5588adcd2033ad5d32bbb9fb470c9615c20 (patch)
tree2db91ff41fc80c764dd0a9f43fd8aeddf58da8ad /src
parentremove my drama comment (diff)
downloadinkscape-a26ea5588adcd2033ad5d32bbb9fb470c9615c20.tar.gz
inkscape-a26ea5588adcd2033ad5d32bbb9fb470c9615c20.zip
Fized crashes & odd behaviour when resizing, zooming and rotating feTurbulence
(bzr r4187)
Diffstat (limited to 'src')
-rw-r--r--src/display/nr-filter-turbulence.cpp52
-rw-r--r--src/display/nr-filter-turbulence.h16
-rw-r--r--src/display/nr-filter-units.cpp21
-rw-r--r--src/display/nr-filter-units.h8
-rw-r--r--src/libnr/nr-point-l.h10
-rw-r--r--src/libnr/nr-rect-l.h10
6 files changed, 90 insertions, 27 deletions
diff --git a/src/display/nr-filter-turbulence.cpp b/src/display/nr-filter-turbulence.cpp
index 2c5d0ee64..869c66fcf 100644
--- a/src/display/nr-filter-turbulence.cpp
+++ b/src/display/nr-filter-turbulence.cpp
@@ -14,6 +14,7 @@
#include "display/nr-filter-turbulence.h"
#include "display/nr-filter-units.h"
#include "display/nr-filter-utils.h"
+#include "libnr/nr-rect-l.h"
#include <math.h>
namespace NR {
@@ -24,6 +25,7 @@ FilterTurbulence::FilterTurbulence()
numOctaves(1),
seed(0),
updated(false),
+ updated_area(IPoint(), IPoint()),
pix(NULL),
fTileWidth(10), //guessed
fTileHeight(10), //guessed
@@ -37,7 +39,12 @@ FilterPrimitive * FilterTurbulence::create() {
}
FilterTurbulence::~FilterTurbulence()
-{}
+{
+ if (pix) {
+ nr_pixblock_release(pix);
+ delete pix;
+ }
+}
void FilterTurbulence::set_baseFrequency(int axis, double freq){
if (axis==0) XbaseFrequency=freq;
@@ -64,19 +71,28 @@ void FilterTurbulence::set_updated(bool u){
updated=u;
}
-void FilterTurbulence::update_pixbuffer(FilterSlot &slot) {
+void FilterTurbulence::update_pixbuffer(FilterSlot &slot, IRect &area) {
//g_warning("update_pixbuf");
- int bbox_x0 = (int) slot.get_arenaitem()->bbox.x0;
- int bbox_y0 = (int) slot.get_arenaitem()->bbox.y0;
- int bbox_x1 = (int) slot.get_arenaitem()->bbox.x1;
- int bbox_y1 = (int) slot.get_arenaitem()->bbox.y1;
+ int bbox_x0 = area.min()[X];
+ int bbox_y0 = area.min()[Y];
+ int bbox_x1 = area.max()[X];
+ int bbox_y1 = area.max()[Y];
int w = bbox_x1 - bbox_x0;
int h = bbox_y1 - bbox_y0;
if (!pix){
pix = new NRPixBlock;
- nr_pixblock_setup_fast(pix, NR_PIXBLOCK_MODE_R8G8B8A8P, bbox_x0, bbox_y0, bbox_x1, bbox_y1, true);
+ nr_pixblock_setup_fast(pix, NR_PIXBLOCK_MODE_R8G8B8A8N, bbox_x0, bbox_y0, bbox_x1, bbox_y1, true);
+ pix_data = NR_PIXBLOCK_PX(pix);
+ }
+ else if (bbox_x0 != pix->area.x0 || bbox_y0 != pix->area.y0 ||
+ bbox_x1 != pix->area.x1 || bbox_y1 != pix->area.y1)
+ {
+ /* TODO: release-setup cycle not actually needed, if pixblock
+ * width and height don't change */
+ nr_pixblock_release(pix);
+ nr_pixblock_setup_fast(pix, NR_PIXBLOCK_MODE_R8G8B8A8N, bbox_x0, bbox_y0, bbox_x1, bbox_y1, true);
pix_data = NR_PIXBLOCK_PX(pix);
}
@@ -104,11 +120,14 @@ void FilterTurbulence::update_pixbuffer(FilterSlot &slot) {
}
}
updated=true;
+ updated_area = area;
}
-int FilterTurbulence::render(FilterSlot &slot, FilterUnits const &/*units*/) {
+int FilterTurbulence::render(FilterSlot &slot, FilterUnits const &units) {
//g_warning("render");
- if (!updated) update_pixbuffer(slot);
+ IRect area = units.get_pixblock_filterarea_paraller();
+ // TODO: could be faster - updated_area only has to be same size as area
+ if (!updated || updated_area != area) update_pixbuffer(slot, area);
NRPixBlock *in = slot.get(_input);
NRPixBlock *out = new NRPixBlock;
@@ -116,16 +135,17 @@ int FilterTurbulence::render(FilterSlot &slot, FilterUnits const &/*units*/) {
int x0 = in->area.x0, y0 = in->area.y0;
int x1 = in->area.x1, y1 = in->area.y1;
int w = x1 - x0;
- nr_pixblock_setup_fast(out, in->mode, x0, y0, x1, y1, true);
+ nr_pixblock_setup_fast(out, NR_PIXBLOCK_MODE_R8G8B8A8N, x0, y0, x1, y1, true);
- int bbox_x0 = (int) slot.get_arenaitem()->bbox.x0;
- int bbox_y0 = (int) slot.get_arenaitem()->bbox.y0;
- int bbox_x1 = (int) slot.get_arenaitem()->bbox.x1;
+ int bbox_x0 = area.min()[X];
+ int bbox_y0 = area.min()[Y];
+ int bbox_x1 = area.max()[X];
+ int bbox_y1 = area.max()[Y];
int bbox_w = bbox_x1 - bbox_x0;
unsigned char *out_data = NR_PIXBLOCK_PX(out);
- for (x=x0; x < x1; x++){
- for (y=y0; y < y1; y++){
+ for (x = std::max(x0, bbox_x0); x < std::min(x1, bbox_x1); x++){
+ for (y = std::max(y0, bbox_y0); y < std::min(y1, bbox_y1); y++){
out_data[4*((x - x0)+w*(y - y0))] = pix_data[4*(x - bbox_x0 + bbox_w*(y - bbox_y0)) ];
out_data[4*((x - x0)+w*(y - y0)) + 1] = pix_data[4*(x - bbox_x0 + bbox_w*(y - bbox_y0))+1];
out_data[4*((x - x0)+w*(y - y0)) + 2] = pix_data[4*(x - bbox_x0 + bbox_w*(y - bbox_y0))+2];
@@ -154,7 +174,7 @@ long FilterTurbulence::TurbulenceRandom(long lSeed)
void FilterTurbulence::TurbulenceInit(long lSeed)
{
-g_warning("init");
+//g_warning("init");
double s;
int i, j, k;
lSeed = Turbulence_setup_seed(lSeed);
diff --git a/src/display/nr-filter-turbulence.h b/src/display/nr-filter-turbulence.h
index 144e3ec4c..bfbacc9f3 100644
--- a/src/display/nr-filter-turbulence.h
+++ b/src/display/nr-filter-turbulence.h
@@ -16,6 +16,7 @@
#include "display/nr-filter-primitive.h"
#include "display/nr-filter-slot.h"
#include "display/nr-filter-units.h"
+#include "libnr/nr-rect-l.h"
namespace NR {
@@ -59,14 +60,14 @@ public:
virtual ~FilterTurbulence();
virtual int render(FilterSlot &slot, FilterUnits const &units);
- virtual void update_pixbuffer(FilterSlot &slot);
+ void update_pixbuffer(FilterSlot &slot, IRect &area);
- virtual void set_baseFrequency(int axis, double freq);
- virtual void set_numOctaves(int num);
- virtual void set_seed(double s);
- virtual void set_stitchTiles(bool st);
- virtual void set_type(FilterTurbulenceType t);
- virtual void set_updated(bool u);
+ void set_baseFrequency(int axis, double freq);
+ void set_numOctaves(int num);
+ void set_seed(double s);
+ void set_stitchTiles(bool st);
+ void set_type(FilterTurbulenceType t);
+ void set_updated(bool u);
virtual FilterTraits get_input_traits();
private:
@@ -82,6 +83,7 @@ private:
bool stitchTiles;
FilterTurbulenceType type;
bool updated;
+ IRect updated_area;
NRPixBlock *pix;
unsigned char *pix_data;
diff --git a/src/display/nr-filter-units.cpp b/src/display/nr-filter-units.cpp
index 2c84800d6..0cad1b4c1 100644
--- a/src/display/nr-filter-units.cpp
+++ b/src/display/nr-filter-units.cpp
@@ -14,6 +14,7 @@
#include "display/nr-filter-units.h"
#include "libnr/nr-matrix.h"
#include "libnr/nr-rect.h"
+#include "libnr/nr-rect-l.h"
#include "libnr/nr-scale.h"
#include "sp-filter-units.h"
@@ -71,8 +72,8 @@ Matrix FilterUnits::get_matrix_user2pb() const {
u2pb[1] = 0;
u2pb[2] = 0;
u2pb[3] = resolution_y / (filter_area.max()[Y] - filter_area.min()[Y]);
- u2pb[4] = 0;
- u2pb[5] = 0;
+ u2pb[4] = ctm[4];
+ u2pb[5] = ctm[5];
}
return u2pb;
@@ -126,6 +127,22 @@ Matrix FilterUnits::get_matrix_pb2display() const {
return pb2d;
}
+IRect FilterUnits::get_pixblock_filterarea_paraller() const {
+ int min_x = INT_MAX, min_y = INT_MAX, max_x = INT_MIN, max_y = INT_MIN;
+ Matrix u2pb = get_matrix_user2pb();
+
+ for (int i = 0 ; i < 4 ; i++) {
+ Point p = filter_area.corner(i);
+ p *= u2pb;
+ if (p[X] < min_x) min_x = (int)std::floor(p[X]);
+ if (p[X] > max_x) max_x = (int)std::ceil(p[X]);
+ if (p[Y] < min_y) min_y = (int)std::floor(p[Y]);
+ if (p[Y] > max_y) max_y = (int)std::ceil(p[Y]);
+ }
+ IRect ret(IPoint(min_x, min_y), IPoint(max_x, max_y));
+ return ret;
+}
+
FilterUnits& FilterUnits::operator=(FilterUnits const &other) {
filterUnits = other.filterUnits;
primitiveUnits = other.primitiveUnits;
diff --git a/src/display/nr-filter-units.h b/src/display/nr-filter-units.h
index 8ebb50327..7f90d6d31 100644
--- a/src/display/nr-filter-units.h
+++ b/src/display/nr-filter-units.h
@@ -15,6 +15,7 @@
#include "sp-filter-units.h"
#include "libnr/nr-matrix.h"
#include "libnr/nr-rect.h"
+#include "libnr/nr-rect-l.h"
namespace NR {
@@ -84,6 +85,13 @@ public:
*/
Matrix get_matrix_pb2display() const;
+ /**
+ * Returns the filter area in pixblock coordinates.
+ * NOTE: use only in filters, that define TRAIT_PARALLER in
+ * get_input_traits. The filter effects area may not be representable
+ * by simple rectangle otherwise. */
+ IRect get_pixblock_filterarea_paraller() const;
+
FilterUnits& operator=(FilterUnits const &other);
private:
diff --git a/src/libnr/nr-point-l.h b/src/libnr/nr-point-l.h
index 8ddfd5e6f..4ae1a8b82 100644
--- a/src/libnr/nr-point-l.h
+++ b/src/libnr/nr-point-l.h
@@ -73,7 +73,15 @@ public:
}
return *this;
}
-
+
+ bool operator==(IPoint const &other) const {
+ return _pt[X] == other[X] && _pt[Y] == other[Y];
+ }
+
+ bool operator!=(IPoint const &other) const {
+ return _pt[X] != other[X] || _pt[Y] != other[Y];
+ }
+
private:
ICoord _pt[2];
};
diff --git a/src/libnr/nr-rect-l.h b/src/libnr/nr-rect-l.h
index b84a8f0cb..18065d1d7 100644
--- a/src/libnr/nr-rect-l.h
+++ b/src/libnr/nr-rect-l.h
@@ -19,7 +19,7 @@ class IRect {
public:
IRect(const NRRectL& r) : _min(r.x0, r.y0), _max(r.x1, r.y1) {}
IRect(const IRect& r) : _min(r._min), _max(r._max) {}
- IRect(const IPoint &p0, const IPoint &p1);
+ IRect(const IPoint &p0, const IPoint &p1) : _min(p0), _max(p1) {}
/** as not all Rects are representable by IRects this gives the smallest IRect that contains
* r. */
@@ -84,6 +84,14 @@ public:
/** Returns the smallest rectangle that encloses both rectangles. */
static IRect union_bounds(const IRect &a, const IRect &b);
+ bool operator==(const IRect &other) const {
+ return (min() == other.min()) && (max() == other.max());
+ }
+
+ bool operator!=(const IRect &other) const {
+ return (min() != other.min()) || (max() != other.max());
+ }
+
private:
IRect() {}