From 1a37ce4a40095c20d83ed6ab3dce34f53bac1b65 Mon Sep 17 00:00:00 2001 From: kiirala Date: Thu, 6 Dec 2007 23:31:29 +0000 Subject: [PATCH] Fized crashes & odd behaviour when resizing, zooming and rotating feTurbulence --- src/display/nr-filter-turbulence.cpp | 52 +++++++++++++++++++--------- src/display/nr-filter-turbulence.h | 16 +++++---- src/display/nr-filter-units.cpp | 21 +++++++++-- src/display/nr-filter-units.h | 8 +++++ src/libnr/nr-point-l.h | 10 +++++- src/libnr/nr-rect-l.h | 10 +++++- 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 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() {} -- 2.30.2