diff options
| author | Niko Kiirala <niko@kiirala.com> | 2007-07-09 12:04:51 +0000 |
|---|---|---|
| committer | kiirala <kiirala@users.sourceforge.net> | 2007-07-09 12:04:51 +0000 |
| commit | d07f036c6e1861995750fa58322b561060eba0ee (patch) | |
| tree | d1d1c10e592d5e69e28ce36e7c1262328dbea2af /src/display | |
| parent | fix 1731457 (diff) | |
| download | inkscape-d07f036c6e1861995750fa58322b561060eba0ee.tar.gz inkscape-d07f036c6e1861995750fa58322b561060eba0ee.zip | |
First version of feComposite filter effect renderer
(bzr r3201)
Diffstat (limited to 'src/display')
| -rw-r--r-- | src/display/Makefile_insert | 3 | ||||
| -rw-r--r-- | src/display/nr-filter-blend.cpp | 139 | ||||
| -rw-r--r-- | src/display/nr-filter-composite.cpp | 235 | ||||
| -rw-r--r-- | src/display/nr-filter-composite.h | 54 | ||||
| -rw-r--r-- | src/display/nr-filter-pixops.h | 148 | ||||
| -rw-r--r-- | src/display/nr-filter-skeleton.cpp | 2 | ||||
| -rw-r--r-- | src/display/nr-filter-skeleton.h | 2 | ||||
| -rw-r--r-- | src/display/nr-filter.cpp | 4 |
8 files changed, 471 insertions, 116 deletions
diff --git a/src/display/Makefile_insert b/src/display/Makefile_insert index 462da04c5..1a4c01011 100644 --- a/src/display/Makefile_insert +++ b/src/display/Makefile_insert @@ -73,10 +73,13 @@ display_libspdisplay_a_SOURCES = \ display/nr-filter-blend.h \ display/nr-filter-offset.cpp \ display/nr-filter-offset.h \ + display/nr-filter-composite.h \ + display/nr-filter-composite.cpp \ display/nr-filter-slot.cpp \ display/nr-filter-slot.h \ display/nr-filter-getalpha.cpp \ display/nr-filter-getalpha.h \ + display/nr-filter-pixops.h \ display/nr-filter-types.h \ display/pixblock-scaler.cpp \ display/pixblock-scaler.h \ diff --git a/src/display/nr-filter-blend.cpp b/src/display/nr-filter-blend.cpp index 0e2f965b7..b02b20cbf 100644 --- a/src/display/nr-filter-blend.cpp +++ b/src/display/nr-filter-blend.cpp @@ -15,6 +15,7 @@ */ #include "display/nr-filter-blend.h" +#include "display/nr-filter-pixops.h" #include "display/nr-filter-primitive.h" #include "display/nr-filter-slot.h" #include "display/nr-filter-types.h" @@ -23,107 +24,7 @@ #include "libnr/nr-blit.h" #include "libnr/nr-pixops.h" -template <void(*blend)(unsigned char *cr, unsigned char const *ca, unsigned char const *cb)> -static void _render(NRPixBlock &out, NRPixBlock &in1, NRPixBlock &in2) { - unsigned char *in1_data = NR_PIXBLOCK_PX(&in1); - unsigned char *in2_data = NR_PIXBLOCK_PX(&in2); - unsigned char *out_data = NR_PIXBLOCK_PX(&out); - unsigned char zero_rgba[4] = {0, 0, 0, 0}; - - if (in1.area.y0 < in2.area.y0) { - // in1 begins before in2 on y-axis - for (int y = in1.area.y0 ; y < in2.area.y0 ; y++) { - int out_line = (y - out.area.y0) * out.rs; - int in_line = (y - in1.area.y0) * in1.rs; - for (int x = in1.area.x0 ; x < in1.area.x1 ; x++) { - blend(out_data + out_line + 4 * (x - out.area.x0), - in1_data + in_line + 4 * (x - in1.area.x0), - zero_rgba); - } - } - } else if (in1.area.y0 > in2.area.y0) { - // in2 begins before in1 on y-axis - for (int y = in2.area.y0 ; y < in1.area.y0 ; y++) { - int out_line = (y - out.area.y0) * out.rs; - int in_line = (y - in2.area.y0) * in2.rs; - for (int x = in2.area.x0 ; x < in2.area.x1 ; x++) { - blend(out_data + out_line + 4 * (x - out.area.x0), - zero_rgba, - in2_data + in_line + 4 * (x - in2.area.x0)); - } - } - } - - for (int y = std::max(in1.area.y0, in2.area.y0) ; - y < std::min(in1.area.y1, in2.area.y1) ; ++y) { - int out_line = (y - out.area.y0) * out.rs; - int in1_line = (y - in1.area.y0) * in1.rs; - int in2_line = (y - in2.area.y0) * in2.rs; - - if (in1.area.x0 < in2.area.x0) { - // in1 begins before in2 on x-axis - for (int x = in1.area.x0 ; x < in2.area.x0 ; ++x) { - blend(out_data + out_line + 4 * (x - out.area.x0), - in1_data + in1_line + 4 * (x - in1.area.x0), - zero_rgba); - } - } else if (in1.area.x0 > in2.area.x0) { - // in2 begins before in1 on x-axis - for (int x = in2.area.x0 ; x < in1.area.x0 ; ++x) { - blend(out_data + out_line + 4 * (x - out.area.x0), - zero_rgba, - in2_data + in2_line + 4 * (x - in2.area.x0)); - } - } - - for (int x = std::max(in1.area.x0, in2.area.x0) ; - x < std::min(in1.area.x1, in2.area.x1) ; ++x) { - blend(out_data + out_line + 4 * (x - out.area.x0), - in1_data + in1_line + 4 * (x - in1.area.x0), - in2_data + in2_line + 4 * (x - in2.area.x0)); - } - - if (in1.area.x1 > in2.area.x1) { - // in1 ends after in2 on x-axis - for (int x = in2.area.x1 ; x < in1.area.x1 ; ++x) { - blend(out_data + out_line + 4 * (x - out.area.x0), - in1_data + in1_line + 4 * (x - in1.area.x0), - zero_rgba); - } - } else if (in1.area.x1 < in2.area.x1) { - // in2 ends after in1 on x-axis - for (int x = in1.area.x1 ; x < in2.area.x1 ; ++x) { - blend(out_data + out_line + 4 * (x - out.area.x0), - zero_rgba, - in2_data + in2_line + 4 * (x - in2.area.x0)); - } - } - } - - if (in1.area.y1 > in2.area.y1) { - // in1 ends after in2 on y-axis - for (int y = in2.area.y1 ; y < in1.area.y1 ; y++) { - int out_line = (y - out.area.y0) * out.rs; - int in_line = (y - in1.area.y0) * in1.rs; - for (int x = in1.area.x0 ; x < in1.area.x1 ; x++) { - blend(out_data + out_line + 4 * (x - out.area.x0), - in1_data + in_line + 4 * (x - in1.area.x0), - zero_rgba); - } - } - } else if (in1.area.y1 < in2.area.y1) { - // in2 ends after in1 on y-axis - for (int y = in1.area.y1 ; y < in2.area.y1 ; y++) { - int out_line = (y - out.area.y0) * out.rs; - int in_line = (y - in2.area.y0) * in2.rs; - for (int x = in2.area.x0 ; x < in2.area.x1 ; x++) { - blend(out_data + out_line + 4 * (x - out.area.x0), - zero_rgba, - in2_data + in_line + 4 * (x - in2.area.x0)); - } - } - } -} +namespace NR { /* * From http://www.w3.org/TR/SVG11/filters.html#feBlend @@ -152,7 +53,9 @@ static void _render(NRPixBlock &out, NRPixBlock &in1, NRPixBlock &in2) { #define SET_ALPHA r[3] = NR_NORMALIZE_21((255 * 255) - (255 - a[3]) * (255 - b[3])) // cr = (1 - qa) * cb + ca -inline void blend_normal(unsigned char *r, unsigned char const *a, unsigned char const *b) { +inline void +blend_normal(unsigned char *r, unsigned char const *a, unsigned char const *b) +{ r[0] = NR_NORMALIZE_21((255 - a[3]) * b[0]) + a[0]; r[1] = NR_NORMALIZE_21((255 - a[3]) * b[1]) + a[1]; r[2] = NR_NORMALIZE_21((255 - a[3]) * b[2]) + a[2]; @@ -160,7 +63,9 @@ inline void blend_normal(unsigned char *r, unsigned char const *a, unsigned char } // cr = (1-qa)*cb + (1-qb)*ca + ca*cb -inline void blend_multiply(unsigned char *r, unsigned char const *a, unsigned char const *b) { +inline void +blend_multiply(unsigned char *r, unsigned char const *a, unsigned char const *b) +{ r[0] = NR_NORMALIZE_21((255 - a[3]) * b[0] + (255 - b[3]) * a[0] + a[0] * b[0]); r[1] = NR_NORMALIZE_21((255 - a[3]) * b[1] + (255 - b[3]) * a[1] @@ -171,7 +76,9 @@ inline void blend_multiply(unsigned char *r, unsigned char const *a, unsigned ch } // cr = cb + ca - ca * cb -inline void blend_screen(unsigned char *r, unsigned char const *a, unsigned char const *b) { +inline void +blend_screen(unsigned char *r, unsigned char const *a, unsigned char const *b) +{ r[0] = NR_NORMALIZE_21(b[0] * 255 + a[0] * 255 - a[0] * b[0]); r[1] = NR_NORMALIZE_21(b[1] * 255 + a[1] * 255 - a[1] * b[1]); r[2] = NR_NORMALIZE_21(b[2] * 255 + a[2] * 255 - a[2] * b[2]); @@ -179,7 +86,9 @@ inline void blend_screen(unsigned char *r, unsigned char const *a, unsigned char } // cr = Min ((1 - qa) * cb + ca, (1 - qb) * ca + cb) -inline void blend_darken(unsigned char *r, unsigned char const *a, unsigned char const *b) { +inline void +blend_darken(unsigned char *r, unsigned char const *a, unsigned char const *b) +{ r[0] = std::min(NR_NORMALIZE_21((255 - a[3]) * b[0]) + a[0], NR_NORMALIZE_21((255 - b[3]) * a[0]) + b[0]); r[1] = std::min(NR_NORMALIZE_21((255 - a[3]) * b[1]) + a[1], @@ -190,7 +99,9 @@ inline void blend_darken(unsigned char *r, unsigned char const *a, unsigned char } // cr = Max ((1 - qa) * cb + ca, (1 - qb) * ca + cb) -inline void blend_lighten(unsigned char *r, unsigned char const *a, unsigned char const *b) { +inline void +blend_lighten(unsigned char *r, unsigned char const *a, unsigned char const *b) +{ r[0] = std::max(NR_NORMALIZE_21((255 - a[3]) * b[0]) + a[0], NR_NORMALIZE_21((255 - b[3]) * a[0]) + b[0]); r[1] = std::max(NR_NORMALIZE_21((255 - a[3]) * b[1]) + a[1], @@ -200,8 +111,6 @@ inline void blend_lighten(unsigned char *r, unsigned char const *a, unsigned cha SET_ALPHA; } -namespace NR { - FilterBlend::FilterBlend() : _blend_mode(BLEND_NORMAL), _input2(NR_FILTER_SLOT_NOT_SET) @@ -253,22 +162,26 @@ int FilterBlend::render(FilterSlot &slot, Matrix const &trans) { nr_blit_pixblock_pixblock(in2, original_in2); } + /* 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. + */ switch (_blend_mode) { case BLEND_MULTIPLY: - _render<blend_multiply>(*out, *in1, *in2); + pixops_mix<blend_multiply>(*out, *in1, *in2); break; case BLEND_SCREEN: - _render<blend_screen>(*out, *in1, *in2); + pixops_mix<blend_screen>(*out, *in1, *in2); break; case BLEND_DARKEN: - _render<blend_darken>(*out, *in1, *in2); + pixops_mix<blend_darken>(*out, *in1, *in2); break; case BLEND_LIGHTEN: - _render<blend_lighten>(*out, *in1, *in2); + pixops_mix<blend_lighten>(*out, *in1, *in2); break; case BLEND_NORMAL: default: - _render<blend_normal>(*out, *in1, *in2); + pixops_mix<blend_normal>(*out, *in1, *in2); break; } diff --git a/src/display/nr-filter-composite.cpp b/src/display/nr-filter-composite.cpp new file mode 100644 index 000000000..43580191e --- /dev/null +++ b/src/display/nr-filter-composite.cpp @@ -0,0 +1,235 @@ +/* + * feComposite 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 "isnan.h" +#include "sp-fecomposite.h" +#include "display/nr-filter-composite.h" +#include "display/nr-filter-pixops.h" +#include "display/nr-filter-slot.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])); +} + +inline void +composite_in(unsigned char *r, unsigned char const *a, unsigned char const *b) +{ + r[0] = NR_NORMALIZE_21(a[0] * b[3]); + r[1] = NR_NORMALIZE_21(a[1] * b[3]); + r[2] = NR_NORMALIZE_21(a[2] * b[3]); + r[3] = NR_NORMALIZE_21(a[3] * b[3]); +} + +inline void +composite_out(unsigned char *r, unsigned char const *a, unsigned char const *b) +{ + r[0] = NR_NORMALIZE_21(a[0] * (255 - b[3])); + r[1] = NR_NORMALIZE_21(a[1] * (255 - b[3])); + r[2] = NR_NORMALIZE_21(a[2] * (255 - b[3])); + r[3] = NR_NORMALIZE_21(a[3] * (255 - b[3])); +} + +inline void +composite_atop(unsigned char *r, unsigned char const *a, unsigned char const *b) +{ + r[0] = NR_NORMALIZE_21(a[0] * b[3] + b[0] * (255 - a[3])); + r[1] = NR_NORMALIZE_21(a[1] * b[3] + b[1] * (255 - a[3])); + r[2] = NR_NORMALIZE_21(a[2] * b[3] + b[2] * (255 - a[3])); + r[3] = b[3]; +} + +inline void +composite_xor(unsigned char *r, unsigned char const *a, unsigned char const *b) +{ + r[0] = NR_NORMALIZE_21(a[0] * (255 - b[3]) + b[0] * (255 - a[3])); + r[1] = NR_NORMALIZE_21(a[1] * (255 - b[3]) + b[1] * (255 - a[3])); + r[2] = NR_NORMALIZE_21(a[2] * (255 - b[3]) + b[2] * (255 - a[3])); + r[3] = NR_NORMALIZE_21(a[3] * (255 - b[3]) + b[3] * (255 - a[3])); +} + +static int clamp(int val) { + if (val < 0) return 0; + if (val > 255) return 255; + return val; +} + +// BUGBUG / TODO +// This makes arithmetic compositing non re-entrant and non thread safe. +static int arith_k1, arith_k2, arith_k3, arith_k4; +inline void +composite_arithmetic(unsigned char *r, unsigned char const *a, unsigned char const *b) +{ + r[0] = clamp(NR_NORMALIZE_31(arith_k1 * a[0] * b[0] + + arith_k2 * a[0] + arith_k3 * b[0] + arith_k4)); + r[1] = clamp(NR_NORMALIZE_31(arith_k1 * a[1] * b[1] + + arith_k2 * a[1] + arith_k3 * b[1] + arith_k4)); + r[2] = clamp(NR_NORMALIZE_31(arith_k1 * a[2] * b[2] + + arith_k2 * a[2] + arith_k3 * b[2] + arith_k4)); + r[3] = clamp(NR_NORMALIZE_31(arith_k1 * a[3] * b[3] + + arith_k2 * a[3] + arith_k3 * b[3] + arith_k4)); +} + +namespace NR { + +FilterComposite::FilterComposite() : + op(COMPOSITE_DEFAULT), k1(0), k2(0), k3(0), k4(0), + _input2(NR::NR_FILTER_SLOT_NOT_SET) +{} + +FilterPrimitive * FilterComposite::create() { + return new FilterComposite(); +} + +FilterComposite::~FilterComposite() +{} + +int FilterComposite::render(FilterSlot &slot, Matrix const &trans) { + NRPixBlock *in1 = slot.get(_input); + NRPixBlock *in2 = slot.get(_input2); + NRPixBlock *original_in1 = in1; + NRPixBlock *original_in2 = in2; + NRPixBlock *out; + + // Bail out if either one of source images is missing + if (!in1 || !in2) { + g_warning("Missing source image for feComposite (in=%d in2=%d)", _input, _input2); + return 1; + } + + out = new NRPixBlock; + NRRectL out_area; + nr_rect_l_union(&out_area, &in1->area, &in2->area); + nr_pixblock_setup_fast(out, NR_PIXBLOCK_MODE_R8G8B8A8P, + out_area.x0, out_area.y0, out_area.x1, out_area.y1, + true); + + // Blending modes are defined for premultiplied RGBA values, + // thus convert them to that format before blending + if (in1->mode != NR_PIXBLOCK_MODE_R8G8B8A8P) { + in1 = new NRPixBlock; + nr_pixblock_setup_fast(in1, NR_PIXBLOCK_MODE_R8G8B8A8P, + original_in1->area.x0, original_in1->area.y0, + original_in1->area.x1, original_in1->area.y1, + false); + nr_blit_pixblock_pixblock(in1, original_in1); + } + if (in2->mode != NR_PIXBLOCK_MODE_R8G8B8A8P) { + in2 = new NRPixBlock; + nr_pixblock_setup_fast(in2, NR_PIXBLOCK_MODE_R8G8B8A8P, + original_in2->area.x0, original_in2->area.y0, + original_in2->area.x1, original_in2->area.y1, + false); + nr_blit_pixblock_pixblock(in2, original_in2); + } + + /* 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. + */ + switch (op) { + case COMPOSITE_IN: + pixops_mix<composite_in>(*out, *in1, *in2); + break; + case COMPOSITE_OUT: + pixops_mix<composite_out>(*out, *in1, *in2); + break; + case COMPOSITE_ATOP: + pixops_mix<composite_atop>(*out, *in1, *in2); + break; + case COMPOSITE_XOR: + pixops_mix<composite_xor>(*out, *in1, *in2); + break; + case COMPOSITE_ARITHMETIC: + arith_k1 = (int)(k1 * 255); + arith_k2 = (int)(k2 * 255 * 255); + arith_k3 = (int)(k3 * 255 * 255); + arith_k4 = (int)(k4 * 255 * 255 * 255); + pixops_mix<composite_arithmetic>(*out, *in1, *in2); + break; + case COMPOSITE_DEFAULT: + case COMPOSITE_OVER: + default: + pixops_mix<composite_over>(*out, *in1, *in2); + break; + } + + if (in1 != original_in1) { + nr_pixblock_release(in1); + delete in1; + } + if (in2 != original_in2) { + nr_pixblock_release(in2); + delete in2; + } + + out->empty = FALSE; + slot.set(_output, out); + + return 0; +} + +void FilterComposite::set_input(int input) { + _input = input; +} + +void FilterComposite::set_input(int input, int slot) { + if (input == 0) _input = slot; + if (input == 1) _input2 = slot; +} + +void FilterComposite::set_operator(FeCompositeOperator op) { + if (op == COMPOSITE_DEFAULT) { + this->op = COMPOSITE_OVER; + } else if (op == COMPOSITE_OVER || + op == COMPOSITE_IN || + op == COMPOSITE_OUT || + op == COMPOSITE_ATOP || + op == COMPOSITE_XOR || + op == COMPOSITE_ARITHMETIC) + { + this->op = op; + } +} + +void FilterComposite::set_arithmetic(double k1, double k2, double k3, double k4) { + if (!isFinite(k1) || !isFinite(k2) || !isFinite(k3) || !isFinite(k4)) { + g_warning("Non-finite parameter for feComposite arithmetic operator"); + return; + } + this->k1 = k1; + this->k2 = k2; + this->k3 = k3; + this->k4 = k4; +} + +} /* 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-composite.h b/src/display/nr-filter-composite.h new file mode 100644 index 000000000..a1bbbb186 --- /dev/null +++ b/src/display/nr-filter-composite.h @@ -0,0 +1,54 @@ +#ifndef __NR_FILTER_COMPOSITE_H__ +#define __NR_FILTER_COMPOSITE_H__ + +/* + * feComposite 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 "sp-fecomposite.h" +#include "display/nr-filter-primitive.h" +#include "display/nr-filter-slot.h" +#include "libnr/nr-matrix.h" + +namespace NR { + +class FilterComposite : public FilterPrimitive { +public: + FilterComposite(); + static FilterPrimitive *create(); + virtual ~FilterComposite(); + + virtual int render(FilterSlot &slot, Matrix const &trans); + + virtual void set_input(int input); + virtual void set_input(int input, int slot); + + void set_operator(FeCompositeOperator op); + void set_arithmetic(double k1, double k2, double k3, double k4); + +private: + FeCompositeOperator op; + double k1, k2, k3, k4; + int _input2; +}; + +} /* namespace NR */ + +#endif /* __NR_FILTER_COMPOSITE_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-pixops.h b/src/display/nr-filter-pixops.h new file mode 100644 index 000000000..2baf3422b --- /dev/null +++ b/src/display/nr-filter-pixops.h @@ -0,0 +1,148 @@ +#ifndef __NR_FILTER_PIXOPS_H__ +#define __NR_FILTER_PIXOPS_H__ + +/* + * Per-pixel image manipulation functions. + * These can be used by all filter primitives, which combine two images on + * per-pixel basis. These are at least feBlend, feComposite and feMerge. + * + * Authors: + * Niko Kiirala <niko@kiirala.com> + * + * Copyright (C) 2007 authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +namespace NR { + +/** + * Mixes the two input images using the function given as template. + * The result is placed in out. + * The mixing function should have the following type: + * void mix(unsigned char *result, unsigned char const *in1, + * unsigned char const *in2); + * Each of the parameters for mix-function is a pointer to four bytes of data, + * giving the RGBA values for that pixel. The mix function must only access + * the four bytes beginning at a pointer given as parameter. + */ +/* + * The implementation is in a header file because of the template. It has to + * be in the same compilation unit as the code using it. Otherwise, linking + * the program will not succeed. + */ +template <void(*blend)(unsigned char *cr, unsigned char const *ca, unsigned char const *cb)> +void pixops_mix(NRPixBlock &out, NRPixBlock &in1, NRPixBlock &in2) { + unsigned char *in1_data = NR_PIXBLOCK_PX(&in1); + unsigned char *in2_data = NR_PIXBLOCK_PX(&in2); + unsigned char *out_data = NR_PIXBLOCK_PX(&out); + unsigned char zero_rgba[4] = {0, 0, 0, 0}; + + if (in1.area.y0 < in2.area.y0) { + // in1 begins before in2 on y-axis + for (int y = in1.area.y0 ; y < in2.area.y0 ; y++) { + int out_line = (y - out.area.y0) * out.rs; + int in_line = (y - in1.area.y0) * in1.rs; + for (int x = in1.area.x0 ; x < in1.area.x1 ; x++) { + blend(out_data + out_line + 4 * (x - out.area.x0), + in1_data + in_line + 4 * (x - in1.area.x0), + zero_rgba); + } + } + } else if (in1.area.y0 > in2.area.y0) { + // in2 begins before in1 on y-axis + for (int y = in2.area.y0 ; y < in1.area.y0 ; y++) { + int out_line = (y - out.area.y0) * out.rs; + int in_line = (y - in2.area.y0) * in2.rs; + for (int x = in2.area.x0 ; x < in2.area.x1 ; x++) { + blend(out_data + out_line + 4 * (x - out.area.x0), + zero_rgba, + in2_data + in_line + 4 * (x - in2.area.x0)); + } + } + } + + for (int y = std::max(in1.area.y0, in2.area.y0) ; + y < std::min(in1.area.y1, in2.area.y1) ; ++y) { + int out_line = (y - out.area.y0) * out.rs; + int in1_line = (y - in1.area.y0) * in1.rs; + int in2_line = (y - in2.area.y0) * in2.rs; + + if (in1.area.x0 < in2.area.x0) { + // in1 begins before in2 on x-axis + for (int x = in1.area.x0 ; x < in2.area.x0 ; ++x) { + blend(out_data + out_line + 4 * (x - out.area.x0), + in1_data + in1_line + 4 * (x - in1.area.x0), + zero_rgba); + } + } else if (in1.area.x0 > in2.area.x0) { + // in2 begins before in1 on x-axis + for (int x = in2.area.x0 ; x < in1.area.x0 ; ++x) { + blend(out_data + out_line + 4 * (x - out.area.x0), + zero_rgba, + in2_data + in2_line + 4 * (x - in2.area.x0)); + } + } + + for (int x = std::max(in1.area.x0, in2.area.x0) ; + x < std::min(in1.area.x1, in2.area.x1) ; ++x) { + blend(out_data + out_line + 4 * (x - out.area.x0), + in1_data + in1_line + 4 * (x - in1.area.x0), + in2_data + in2_line + 4 * (x - in2.area.x0)); + } + + if (in1.area.x1 > in2.area.x1) { + // in1 ends after in2 on x-axis + for (int x = in2.area.x1 ; x < in1.area.x1 ; ++x) { + blend(out_data + out_line + 4 * (x - out.area.x0), + in1_data + in1_line + 4 * (x - in1.area.x0), + zero_rgba); + } + } else if (in1.area.x1 < in2.area.x1) { + // in2 ends after in1 on x-axis + for (int x = in1.area.x1 ; x < in2.area.x1 ; ++x) { + blend(out_data + out_line + 4 * (x - out.area.x0), + zero_rgba, + in2_data + in2_line + 4 * (x - in2.area.x0)); + } + } + } + + if (in1.area.y1 > in2.area.y1) { + // in1 ends after in2 on y-axis + for (int y = in2.area.y1 ; y < in1.area.y1 ; y++) { + int out_line = (y - out.area.y0) * out.rs; + int in_line = (y - in1.area.y0) * in1.rs; + for (int x = in1.area.x0 ; x < in1.area.x1 ; x++) { + blend(out_data + out_line + 4 * (x - out.area.x0), + in1_data + in_line + 4 * (x - in1.area.x0), + zero_rgba); + } + } + } else if (in1.area.y1 < in2.area.y1) { + // in2 ends after in1 on y-axis + for (int y = in1.area.y1 ; y < in2.area.y1 ; y++) { + int out_line = (y - out.area.y0) * out.rs; + int in_line = (y - in2.area.y0) * in2.rs; + for (int x = in2.area.x0 ; x < in2.area.x1 ; x++) { + blend(out_data + out_line + 4 * (x - out.area.x0), + zero_rgba, + in2_data + in_line + 4 * (x - in2.area.x0)); + } + } + } +} + +} // namespace NR + +#endif // __NR_FILTER_PIXOPS_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-skeleton.cpp b/src/display/nr-filter-skeleton.cpp index f595f13f1..68c38c4b2 100644 --- a/src/display/nr-filter-skeleton.cpp +++ b/src/display/nr-filter-skeleton.cpp @@ -5,7 +5,7 @@ * type, like gaussian or blend in respective case. * * This can be accomplished with the following sed command: - * sed -e "s/Skeleton/Name/g" -e "s/skeleton/name" -e "s/SKELETON/NAME" + * sed -e "s/Skeleton/Name/g" -e "s/skeleton/name/" -e "s/SKELETON/NAME/" * nr-filter-skeleton.cpp >nr-filter-name.cpp * * (on one line, replace occurences of 'name' with your filter name) diff --git a/src/display/nr-filter-skeleton.h b/src/display/nr-filter-skeleton.h index ae3a08046..edba5c2f1 100644 --- a/src/display/nr-filter-skeleton.h +++ b/src/display/nr-filter-skeleton.h @@ -8,7 +8,7 @@ * type, like gaussian or blend in respective case. * * This can be accomplished with the following sed command: - * sed -e "s/Skeleton/Name/g" -e "s/skeleton/name" -e "s/SKELETON/NAME" + * sed -e "s/Skeleton/Name/g" -e "s/skeleton/name/" -e "s/SKELETON/NAME/" * nr-filter-skeleton.h >nr-filter-name.h * * (on one line, replace occurences of 'name' with your filter name) diff --git a/src/display/nr-filter.cpp b/src/display/nr-filter.cpp index 33e89ac3e..61571f43b 100644 --- a/src/display/nr-filter.cpp +++ b/src/display/nr-filter.cpp @@ -20,9 +20,11 @@ #include "display/nr-filter-types.h" #include "display/pixblock-scaler.h" #include "display/pixblock-transform.h" + #include "display/nr-filter-gaussian.h" #include "display/nr-filter-blend.h" #include "display/nr-filter-offset.h" +#include "display/nr-filter-composite.h" #include "display/nr-arena-item.h" #include "libnr/nr-pixblock.h" @@ -309,7 +311,7 @@ void Filter::_create_constructor_table() _constructor[NR_FILTER_BLEND] = &FilterBlend::create; _constructor[NR_FILTER_COLORMATRIX] = NULL; _constructor[NR_FILTER_COMPONENTTRANSFER] = NULL; - _constructor[NR_FILTER_COMPOSITE] = NULL; + _constructor[NR_FILTER_COMPOSITE] = &FilterComposite::create; _constructor[NR_FILTER_CONVOLVEMATRIX] = NULL; _constructor[NR_FILTER_DIFFUSELIGHTING] = NULL; _constructor[NR_FILTER_DISPLACEMENTMAP] = NULL; |
