From 8f2afbd99dcbbe962be70bc574e356b33c8b9537 Mon Sep 17 00:00:00 2001 From: kiirala Date: Mon, 2 Jun 2008 17:46:50 +0000 Subject: [PATCH] Fixed SVG compliance problems with feMorphology (bug 181995 at least) --- src/display/nr-filter-morphology.cpp | 63 ++++++++++++++++++++-------- src/display/nr-filter-morphology.h | 8 ++-- src/sp-femorphology.cpp | 4 +- 3 files changed, 52 insertions(+), 23 deletions(-) diff --git a/src/display/nr-filter-morphology.cpp b/src/display/nr-filter-morphology.cpp index 4ef0b6ad3..7850849f3 100644 --- a/src/display/nr-filter-morphology.cpp +++ b/src/display/nr-filter-morphology.cpp @@ -11,6 +11,9 @@ #include "display/nr-filter-morphology.h" #include "display/nr-filter-units.h" +#include "libnr/nr-blit.h" +#include "libnr/nr-matrix.h" +#include "libnr/nr-matrix-fns.h" namespace NR { @@ -25,7 +28,7 @@ FilterPrimitive * FilterMorphology::create() { FilterMorphology::~FilterMorphology() {} -int FilterMorphology::render(FilterSlot &slot, FilterUnits const &/*units*/) { +int FilterMorphology::render(FilterSlot &slot, FilterUnits const &units) { NRPixBlock *in = slot.get(_input); if (!in) { g_warning("Missing source image for feMorphology (in=%d)", _input); @@ -34,12 +37,30 @@ int FilterMorphology::render(FilterSlot &slot, FilterUnits const &/*units*/) { NRPixBlock *out = new NRPixBlock; + // this primitive is defined for premultiplied RGBA values, + // thus convert them to that format + bool free_in_on_exit = false; + if (in->mode != NR_PIXBLOCK_MODE_R8G8B8A8P) { + NRPixBlock *original_in = in; + in = new NRPixBlock; + nr_pixblock_setup_fast(in, NR_PIXBLOCK_MODE_R8G8B8A8P, + original_in->area.x0, original_in->area.y0, + original_in->area.x1, original_in->area.y1, + true); + nr_blit_pixblock_pixblock(in, original_in); + free_in_on_exit = true; + } + + Matrix p2pb = units.get_matrix_primitiveunits2pb(); + int const xradius = (int)round(this->xradius * expansionX(p2pb)); + int const yradius = (int)round(this->yradius * expansionY(p2pb)); + int x0=in->area.x0; int y0=in->area.y0; int x1=in->area.x1; int y1=in->area.y1; int w=x1-x0, h=y1-y0; - int x,y,i,j; + int x, y, i, j; int rmax,gmax,bmax,amax; int rmin,gmin,bmin,amin; @@ -48,14 +69,14 @@ int FilterMorphology::render(FilterSlot &slot, FilterUnits const &/*units*/) { unsigned char *in_data = NR_PIXBLOCK_PX(in); unsigned char *out_data = NR_PIXBLOCK_PX(out); - for(x=xradius; x= w) continue; + for(j = y - yradius ; j < y + yradius ; j++){ + if (j < 0 || j >= h) continue; if(in_data[4*(i + w*j)]>rmax) rmax = in_data[4*(i + w*j)]; if(in_data[4*(i + w*j)+1]>gmax) gmax = in_data[4*(i + w*j)+1]; if(in_data[4*(i + w*j)+2]>bmax) bmax = in_data[4*(i + w*j)+2]; @@ -81,28 +102,36 @@ int FilterMorphology::render(FilterSlot &slot, FilterUnits const &/*units*/) { } } + if (free_in_on_exit) { + nr_pixblock_release(in); + delete in; + } + out->empty = FALSE; slot.set(_output, out); return 0; } -void FilterMorphology::area_enlarge(NRRectL &area, Matrix const &/*trans*/) +void FilterMorphology::area_enlarge(NRRectL &area, Matrix const &trans) { - area.x0-=xradius; - area.x1+=xradius; - area.y0-=yradius; - area.y1+=yradius; + int const enlarge_x = (int)round(this->xradius * expansionX(trans)); + int const enlarge_y = (int)round(this->yradius * expansionY(trans)); + + area.x0 -= enlarge_x; + area.x1 += enlarge_x; + area.y0 -= enlarge_y; + area.y1 += enlarge_y; } void FilterMorphology::set_operator(FilterMorphologyOperator &o){ Operator = o; } -void FilterMorphology::set_xradius(int x){ +void FilterMorphology::set_xradius(double x){ xradius = x; } -void FilterMorphology::set_yradius(int y){ +void FilterMorphology::set_yradius(double y){ yradius = y; } diff --git a/src/display/nr-filter-morphology.h b/src/display/nr-filter-morphology.h index a9435041e..c930c5e0a 100644 --- a/src/display/nr-filter-morphology.h +++ b/src/display/nr-filter-morphology.h @@ -34,13 +34,13 @@ public: virtual void area_enlarge(NRRectL &area, Matrix const &trans); virtual FilterTraits get_input_traits(); void set_operator(FilterMorphologyOperator &o); - void set_xradius(int x); - void set_yradius(int y); + void set_xradius(double x); + void set_yradius(double y); private: FilterMorphologyOperator Operator; - int xradius; - int yradius; + double xradius; + double yradius; }; } /* namespace NR */ diff --git a/src/sp-femorphology.cpp b/src/sp-femorphology.cpp index fa7a3ddb0..33ab62621 100644 --- a/src/sp-femorphology.cpp +++ b/src/sp-femorphology.cpp @@ -213,8 +213,8 @@ static void sp_feMorphology_build_renderer(SPFilterPrimitive *primitive, NR::Fil sp_filter_primitive_renderer_common(primitive, nr_primitive); nr_morphology->set_operator(sp_morphology->Operator); - nr_morphology->set_xradius( (int)sp_morphology->radius.getNumber() ); - nr_morphology->set_yradius( (int)sp_morphology->radius.getOptNumber() ); + nr_morphology->set_xradius( sp_morphology->radius.getNumber() ); + nr_morphology->set_yradius( sp_morphology->radius.getOptNumber() ); } /* -- 2.30.2