diff options
| author | Niko Kiirala <niko@kiirala.com> | 2007-07-26 11:38:36 +0000 |
|---|---|---|
| committer | kiirala <kiirala@users.sourceforge.net> | 2007-07-26 11:38:36 +0000 |
| commit | 13fa505ea30c087ca93f18a64d2a9837cbfd06cf (patch) | |
| tree | 4a799476b76020ac22ec2c8710b22675d571ed93 /src/display | |
| parent | SpinSlider: (diff) | |
| download | inkscape-13fa505ea30c087ca93f18a64d2a9837cbfd06cf.tar.gz inkscape-13fa505ea30c087ca93f18a64d2a9837cbfd06cf.zip | |
Added support for feMerge filter priitive
(bzr r3308)
Diffstat (limited to 'src/display')
| -rw-r--r-- | src/display/Makefile_insert | 2 | ||||
| -rw-r--r-- | src/display/nr-filter-merge.cpp | 140 | ||||
| -rw-r--r-- | src/display/nr-filter-merge.h | 51 | ||||
| -rw-r--r-- | src/display/nr-filter.cpp | 3 |
4 files changed, 195 insertions, 1 deletions
diff --git a/src/display/Makefile_insert b/src/display/Makefile_insert index 624733a42..1713dc751 100644 --- a/src/display/Makefile_insert +++ b/src/display/Makefile_insert @@ -83,6 +83,8 @@ display_libspdisplay_a_SOURCES = \ display/nr-filter-getalpha.h \ display/nr-filter-image.cpp \ display/nr-filter-image.h \ + display/nr-filter-merge.cpp \ + display/nr-filter-merge.h \ display/nr-filter-offset.cpp \ display/nr-filter-offset.h \ display/nr-filter-primitive.cpp \ diff --git a/src/display/nr-filter-merge.cpp b/src/display/nr-filter-merge.cpp new file mode 100644 index 000000000..8650fee8b --- /dev/null +++ b/src/display/nr-filter-merge.cpp @@ -0,0 +1,140 @@ +/* + * feMerge filter effect renderer + * + * Authors: + * Niko Kiirala <niko@kiirala.com> + * + * Copyright (C) 2007 authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include <cmath> +#include <vector> + +#include "isnan.h" +#include "sp-femerge.h" +#include "display/nr-filter-merge.h" +#include "display/nr-filter-pixops.h" +#include "display/nr-filter-slot.h" +#include "display/nr-filter-utils.h" +#include "libnr/nr-blit.h" +#include "libnr/nr-pixblock.h" +#include "libnr/nr-pixops.h" +#include "libnr/nr-matrix.h" + +inline void +composite_over(unsigned char *r, unsigned char const *a, unsigned char const *b) +{ + r[0] = a[0] + NR_NORMALIZE_21(b[0] * (255 - a[3])); + r[1] = a[1] + NR_NORMALIZE_21(b[1] * (255 - a[3])); + r[2] = a[2] + NR_NORMALIZE_21(b[2] * (255 - a[3])); + r[3] = a[3] + NR_NORMALIZE_21(b[3] * (255 - a[3])); +} + +namespace NR { + +FilterMerge::FilterMerge() : + _input_image(1, NR_FILTER_SLOT_NOT_SET) +{} + +FilterPrimitive * FilterMerge::create() { + return new FilterMerge(); +} + +FilterMerge::~FilterMerge() +{} + +int FilterMerge::render(FilterSlot &slot, Matrix const &trans) { + NRPixBlock *in[_input_image.size()]; + NRPixBlock *original_in[_input_image.size()]; + + for (unsigned int i = 0 ; i < _input_image.size() ; i++) { + in[i] = slot.get(_input_image[i]); + original_in[i] = in[i]; + } + + NRPixBlock *out; + + // Bail out if either one of source images is missing + for (unsigned int i = 0 ; i < _input_image.size() ; i++) { + if (!in[i]) { + g_warning("Missing source image for feMerge (number=%d slot=%d)", i, _input_image[i]); + return 1; + } + } + + out = new NRPixBlock; + NRRectL out_area = in[0]->area; + for (unsigned int i = 1 ; i < _input_image.size() ; i++) { + nr_rect_l_union(&out_area, &out_area, &in[i]->area); + } + nr_pixblock_setup_fast(out, NR_PIXBLOCK_MODE_R8G8B8A8P, + out_area.x0, out_area.y0, out_area.x1, out_area.y1, + true); + + // Merge is defined for premultiplied RGBA values, thus convert them to + // that format before blending + for (unsigned int i = 0 ; i < _input_image.size() ; i++) { + if (in[i]->mode != NR_PIXBLOCK_MODE_R8G8B8A8P) { + in[i] = new NRPixBlock; + nr_pixblock_setup_fast(in[i], NR_PIXBLOCK_MODE_R8G8B8A8P, + original_in[i]->area.x0, + original_in[i]->area.y0, + original_in[i]->area.x1, + original_in[i]->area.y1, + false); + nr_blit_pixblock_pixblock(in[i], original_in[i]); + } + } + + /* pixops_mix is defined in display/nr-filter-pixops.h + * It mixes the two input images with the function given as template + * and places the result in output image. + */ + for (unsigned int i = 0 ; i < _input_image.size() ; i++) { + pixops_mix<composite_over>(*out, *in[i], *out); + } + + for (unsigned int i = 0 ; i < _input_image.size() ; i++) { + if (in[i] != original_in[i]) { + nr_pixblock_release(in[i]); + delete in[i]; + } + } + + out->empty = FALSE; + slot.set(_output, out); + + return 0; +} + +void FilterMerge::set_input(int slot) { + _input_image[0] = slot; +} + +void FilterMerge::set_input(int input, int slot) { + if (input < 0) return; + + if (_input_image.size() > input) { + _input_image[input] = slot; + } else { + for (unsigned int i = _input_image.size() ; i < input ; i++) { + _input_image.push_back(NR_FILTER_SLOT_NOT_SET); + } + _input_image.push_back(slot); + } +} + +} /* namespace NR */ + +/* + 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:encoding=utf-8:textwidth=99 : diff --git a/src/display/nr-filter-merge.h b/src/display/nr-filter-merge.h new file mode 100644 index 000000000..a88819c50 --- /dev/null +++ b/src/display/nr-filter-merge.h @@ -0,0 +1,51 @@ +#ifndef __NR_FILTER_MERGE_H__ +#define __NR_FILTER_MERGE_H__ + +/* + * feMerge filter effect renderer + * + * Authors: + * Niko Kiirala <niko@kiirala.com> + * + * Copyright (C) 2007 authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include <vector> + +#include "sp-femerge.h" +#include "display/nr-filter-primitive.h" +#include "display/nr-filter-slot.h" +#include "libnr/nr-matrix.h" + +namespace NR { + +class FilterMerge : public FilterPrimitive { +public: + FilterMerge(); + static FilterPrimitive *create(); + virtual ~FilterMerge(); + + virtual int render(FilterSlot &slot, Matrix const &trans); + + virtual void set_input(int input); + virtual void set_input(int input, int slot); + +private: + std::vector<int> _input_image; +}; + +} /* namespace NR */ + +#endif /* __NR_FILTER_MERGE_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:encoding=utf-8:textwidth=99 : diff --git a/src/display/nr-filter.cpp b/src/display/nr-filter.cpp index f09573eb4..95867363b 100644 --- a/src/display/nr-filter.cpp +++ b/src/display/nr-filter.cpp @@ -28,6 +28,7 @@ #include "display/nr-filter-displacement-map.h" #include "display/nr-filter-gaussian.h" #include "display/nr-filter-image.h" +#include "display/nr-filter-merge.h" #include "display/nr-filter-offset.h" #include "display/nr-filter-specularlighting.h" #include "display/nr-filter-turbulence.h" @@ -326,7 +327,7 @@ void Filter::_create_constructor_table() _constructor[NR_FILTER_FLOOD] = NULL; _constructor[NR_FILTER_GAUSSIANBLUR] = &FilterGaussian::create; _constructor[NR_FILTER_IMAGE] = &FilterImage::create; - _constructor[NR_FILTER_MERGE] = NULL; + _constructor[NR_FILTER_MERGE] = &FilterMerge::create; _constructor[NR_FILTER_MORPHOLOGY] = NULL; _constructor[NR_FILTER_OFFSET] = &FilterOffset::create; _constructor[NR_FILTER_SPECULARLIGHTING] = &FilterSpecularLighting::create; |
