summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorNiko Kiirala <niko@kiirala.com>2007-05-14 12:54:58 +0000
committerkiirala <kiirala@users.sourceforge.net>2007-05-14 12:54:58 +0000
commit532e1380e00f318c0b008a31a4c8b2e3d0492438 (patch)
tree7988fea437cdd63217c65a07f48787285447ac64 /src
parentInitial set of style test. Will uncomment as style code is fixed. (diff)
downloadinkscape-532e1380e00f318c0b008a31a4c8b2e3d0492438.tar.gz
inkscape-532e1380e00f318c0b008a31a4c8b2e3d0492438.zip
Added renderer support for feBlend filter effect
(bzr r3015)
Diffstat (limited to 'src')
-rw-r--r--src/display/Makefile_insert2
-rw-r--r--src/display/nr-arena-group.cpp8
-rw-r--r--src/display/nr-arena-image.cpp8
-rw-r--r--src/display/nr-arena-shape.cpp17
-rw-r--r--src/display/nr-filter-blend.cpp309
-rw-r--r--src/display/nr-filter-blend.h67
-rw-r--r--src/display/nr-filter.cpp12
-rw-r--r--src/sp-feblend.cpp45
-rw-r--r--src/sp-feblend.h7
9 files changed, 461 insertions, 14 deletions
diff --git a/src/display/Makefile_insert b/src/display/Makefile_insert
index ad69c772b..95502170a 100644
--- a/src/display/Makefile_insert
+++ b/src/display/Makefile_insert
@@ -69,6 +69,8 @@ display_libspdisplay_a_SOURCES = \
display/nr-filter-primitive.h \
display/nr-filter-gaussian.cpp \
display/nr-filter-gaussian.h \
+ display/nr-filter-blend.cpp \
+ display/nr-filter-blend.h \
display/nr-filter-slot.cpp \
display/nr-filter-slot.h \
display/nr-filter-types.h \
diff --git a/src/display/nr-arena-group.cpp b/src/display/nr-arena-group.cpp
index 0678eb37e..697ef6a05 100644
--- a/src/display/nr-arena-group.cpp
+++ b/src/display/nr-arena-group.cpp
@@ -19,6 +19,8 @@
#include "style.h"
#include "sp-filter.h"
#include "sp-gaussian-blur.h"
+#include "sp-feblend.h"
+#include "display/nr-filter-blend.h"
static void nr_arena_group_class_init (NRArenaGroupClass *klass);
static void nr_arena_group_init (NRArenaGroup *group);
@@ -219,6 +221,12 @@ void nr_arena_group_set_style (NRArenaGroup *group, SPStyle *style)
else
gaussian->set_deviation((double) num);
}
+ } else if(SP_IS_FEBLEND(primitive)) {
+ // TODO: this is just a test. Besides this whole filter
+ // creation needs to be redone
+ NR::FilterBlend *nrblend = (NR::FilterBlend *) group->filter->add_primitive(NR::NR_FILTER_BLEND);
+ SPFeBlend *spblend = SP_FEBLEND(primitive);
+ nrblend->set_mode(spblend->blend_mode);
}
}
}
diff --git a/src/display/nr-arena-image.cpp b/src/display/nr-arena-image.cpp
index 1b4f3341c..964f7e86f 100644
--- a/src/display/nr-arena-image.cpp
+++ b/src/display/nr-arena-image.cpp
@@ -24,6 +24,8 @@
#include <livarot/Shape.h>
#include "sp-filter.h"
#include "sp-gaussian-blur.h"
+#include "sp-feblend.h"
+#include "display/nr-filter-blend.h"
int nr_arena_image_x_sample = 1;
int nr_arena_image_y_sample = 1;
@@ -392,6 +394,12 @@ void nr_arena_image_set_style (NRArenaImage *image, SPStyle *style)
else
gaussian->set_deviation((double) num);
}
+ } else if(SP_IS_FEBLEND(primitive)) {
+ // TODO: this is just a test. Besides this whole filter
+ // creation needs to be redone
+ NR::FilterBlend *nrblend = (NR::FilterBlend *) image->filter->add_primitive(NR::NR_FILTER_BLEND);
+ SPFeBlend *spblend = SP_FEBLEND(primitive);
+ nrblend->set_mode(spblend->blend_mode);
}
}
}
diff --git a/src/display/nr-arena-shape.cpp b/src/display/nr-arena-shape.cpp
index c5551695f..421627309 100644
--- a/src/display/nr-arena-shape.cpp
+++ b/src/display/nr-arena-shape.cpp
@@ -17,9 +17,6 @@
#include <display/canvas-arena.h>
#include <display/nr-arena.h>
#include <display/nr-arena-shape.h>
-#include "display/nr-filter.h"
-#include "display/nr-filter-gaussian.h"
-#include "display/nr-filter-types.h"
#include <libnr/n-art-bpath.h>
#include <libnr/nr-path.h>
#include <libnr/nr-pixops.h>
@@ -32,9 +29,15 @@
#include <style.h>
#include "prefs-utils.h"
#include "sp-filter.h"
-#include "sp-gaussian-blur.h"
#include "inkscape-cairo.h"
+#include "display/nr-filter.h"
+#include "display/nr-filter-gaussian.h"
+#include "display/nr-filter-types.h"
+#include "sp-gaussian-blur.h"
+#include "sp-feblend.h"
+#include "display/nr-filter-blend.h"
+
#include <cairo.h>
//int showRuns=0;
@@ -1386,6 +1389,12 @@ nr_arena_shape_set_style(NRArenaShape *shape, SPStyle *style)
else
gaussian->set_deviation((double) num);
}
+ } else if(SP_IS_FEBLEND(primitive)) {
+ // TODO: this is just a test. Besides this whole filter
+ // creation needs to be redone
+ NR::FilterBlend *nrblend = (NR::FilterBlend *) shape->filter->add_primitive(NR::NR_FILTER_BLEND);
+ SPFeBlend *spblend = SP_FEBLEND(primitive);
+ nrblend->set_mode(spblend->blend_mode);
}
}
}
diff --git a/src/display/nr-filter-blend.cpp b/src/display/nr-filter-blend.cpp
new file mode 100644
index 000000000..e36574d74
--- /dev/null
+++ b/src/display/nr-filter-blend.cpp
@@ -0,0 +1,309 @@
+/*
+ * SVG feBlend renderer
+ *
+ * "This filter composites two objects together using commonly used
+ * imaging software blending modes. It performs a pixel-wise combination
+ * of two input images."
+ * http://www.w3.org/TR/SVG11/filters.html#feBlend
+ *
+ * Authors:
+ * Niko Kiirala <niko@kiirala.com>
+ *
+ * Copyright (C) 2007 authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "display/nr-filter-blend.h"
+#include "display/nr-filter-primitive.h"
+#include "display/nr-filter-slot.h"
+#include "display/nr-filter-types.h"
+#include "libnr/nr-pixblock.h"
+#include "libnr/nr-matrix.h"
+#include "libnr/nr-blit.h"
+
+static inline int clamp(const int val, const int min, const int max) {
+ if (val < min) return min;
+ if (val > max) return max;
+ return val;
+}
+
+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));
+ }
+ }
+ }
+}
+
+/*
+ * From http://www.w3.org/TR/SVG11/filters.html#feBlend
+ *
+ * For all feBlend modes, the result opacity is computed as follows:
+ * qr = 1 - (1-qa)*(1-qb)
+ *
+ * For the compositing formulas below, the following definitions apply:
+ * cr = Result color (RGB) - premultiplied
+ * qa = Opacity value at a given pixel for image A
+ * qb = Opacity value at a given pixel for image B
+ * ca = Color (RGB) at a given pixel for image A - premultiplied
+ * cb = Color (RGB) at a given pixel for image B - premultiplied
+*/
+
+// cr = (1 - qa) * cb + ca
+inline void blend_normal(unsigned char *r, unsigned char const *a, unsigned char const *b) {
+ r[0] = (((255 - a[3]) * b[0]) >> 8) + a[0];
+ r[1] = (((255 - a[3]) * b[1]) >> 8) + a[1];
+ r[2] = (((255 - a[3]) * b[2]) >> 8) + a[2];
+ r[3] = 255 - (((255 - a[3]) * (255 - b[3])) >> 8);
+}
+
+// cr = (1-qa)*cb + (1-qb)*ca + ca*cb
+inline void blend_multiply(unsigned char *r, unsigned char const *a, unsigned char const *b) {
+ r[0] = ((255 - a[3]) * b[0] + (255 - b[3]) * a[0] + a[0] * b[0]) >> 8;
+ r[1] = ((255 - a[3]) * b[1] + (255 - b[3]) * a[1] + a[1] * b[1]) >> 8;
+ r[2] = ((255 - a[3]) * b[2] + (255 - b[3]) * a[2] + a[2] * b[2]) >> 8;
+ r[3] = 255 - (((255 - a[3]) * (255 - b[3])) >> 8);
+}
+
+// cr = cb + ca - ca * cb
+inline void blend_screen(unsigned char *r, unsigned char const *a, unsigned char const *b) {
+ r[0] = b[0] + a[0] - ((a[0] * b[0]) >> 8);
+ r[1] = b[1] + a[1] - ((a[1] * b[1]) >> 8);
+ r[2] = b[2] + a[2] - ((a[2] * b[2]) >> 8);
+ r[3] = 255 - (((255 - a[3]) * (255 - b[3])) >> 8);
+}
+
+// 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) {
+ r[0] = std::min((((255 - a[3]) * b[0]) >> 8) + a[0],
+ (((255 - b[3]) * a[0]) >> 8) + b[0]);
+ r[1] = std::min((((255 - a[3]) * b[1]) >> 8) + a[1],
+ (((255 - b[3]) * a[1]) >> 8) + b[1]);
+ r[2] = std::min((((255 - a[3]) * b[2]) >> 8) + a[2],
+ (((255 - b[3]) * a[2]) >> 8) + b[2]);
+ r[3] = 255 - (((255 - a[3]) * (255 - b[3])) >> 8);
+}
+
+// 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) {
+ r[0] = std::max((((255 - a[3]) * b[0]) >> 8) + a[0],
+ (((255 - b[3]) * a[0]) >> 8) + b[0]);
+ r[1] = std::max((((255 - a[3]) * b[1]) >> 8) + a[1],
+ (((255 - b[3]) * a[1]) >> 8) + b[1]);
+ r[2] = std::max((((255 - a[3]) * b[2]) >> 8) + a[2],
+ (((255 - b[3]) * a[2]) >> 8) + b[2]);
+ r[3] = 255 - (((255 - a[3]) * (255 - b[3])) >> 8);
+}
+
+namespace NR {
+
+FilterBlend::FilterBlend()
+ : _blend_mode(BLEND_NORMAL),
+ _input2(NR_FILTER_SLOT_NOT_SET)
+{}
+
+FilterPrimitive * FilterBlend::create() {
+ return new FilterBlend();
+}
+
+FilterBlend::~FilterBlend()
+{}
+
+int FilterBlend::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 feBlend (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);
+ }
+
+ switch (_blend_mode) {
+ case BLEND_MULTIPLY:
+ _render<blend_multiply>(*out, *in1, *in2);
+ break;
+ case BLEND_SCREEN:
+ _render<blend_screen>(*out, *in1, *in2);
+ break;
+ case BLEND_DARKEN:
+ _render<blend_darken>(*out, *in1, *in2);
+ break;
+ case BLEND_LIGHTEN:
+ _render<blend_lighten>(*out, *in1, *in2);
+ break;
+ case BLEND_NORMAL:
+ default:
+ _render<blend_normal>(*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 FilterBlend::set_input(int slot) {
+ _input = slot;
+}
+
+void FilterBlend::set_input(int input, int slot) {
+ if (input == 0) _input = slot;
+ if (input == 1) _input2 = slot;
+}
+
+void FilterBlend::set_mode(FilterBlendMode mode) {
+ if (mode == BLEND_NORMAL || mode == BLEND_MULTIPLY ||
+ mode == BLEND_SCREEN || mode == BLEND_DARKEN ||
+ mode == BLEND_LIGHTEN)
+ {
+ _blend_mode = mode;
+ }
+}
+
+} /* 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-blend.h b/src/display/nr-filter-blend.h
new file mode 100644
index 000000000..4787e336e
--- /dev/null
+++ b/src/display/nr-filter-blend.h
@@ -0,0 +1,67 @@
+#ifndef __NR_FILTER_BLEND_H__
+#define __NR_FILTER_BLEND_H__
+
+/*
+ * SVG feBlend renderer
+ *
+ * "This filter composites two objects together using commonly used
+ * imaging software blending modes. It performs a pixel-wise combination
+ * of two input images."
+ * http://www.w3.org/TR/SVG11/filters.html#feBlend
+ *
+ * Authors:
+ * Niko Kiirala <niko@kiirala.com>
+ *
+ * Copyright (C) 2007 authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "display/nr-filter-primitive.h"
+#include "display/nr-filter-slot.h"
+#include "libnr/nr-matrix.h"
+
+namespace NR {
+
+enum FilterBlendMode {
+ BLEND_NORMAL,
+ BLEND_MULTIPLY,
+ BLEND_SCREEN,
+ BLEND_DARKEN,
+ BLEND_LIGHTEN
+};
+
+class FilterBlend : public FilterPrimitive {
+public:
+ FilterBlend();
+ static FilterPrimitive *create();
+ virtual ~FilterBlend();
+
+ virtual int render(FilterSlot &slot, Matrix const &trans);
+
+ virtual void set_input(int slot);
+ virtual void set_input(int input, int slot);
+ void set_mode(FilterBlendMode mode);
+
+private:
+ FilterBlendMode _blend_mode;
+ int _input2;
+};
+
+
+} /* namespace NR */
+
+
+
+
+#endif /* __NR_FILTER_BLEND_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 07c264928..fe33afff0 100644
--- a/src/display/nr-filter.cpp
+++ b/src/display/nr-filter.cpp
@@ -16,11 +16,12 @@
#include "display/nr-filter.h"
#include "display/nr-filter-primitive.h"
-#include "display/nr-filter-gaussian.h"
#include "display/nr-filter-slot.h"
#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-arena-item.h"
#include "libnr/nr-pixblock.h"
@@ -63,7 +64,7 @@ Filter::Filter()
_primitive_count = 0;
_primitive_table_size = 1;
_primitive = new FilterPrimitive*[1];
- _primitive[0] = NULL;
+ _primitive[0] = NULL;
//_primitive_count = 1;
//_primitive[0] = new FilterGaussian;
_common_init();
@@ -213,8 +214,9 @@ int Filter::render(NRArenaItem const *item, NRPixBlock *pb)
slot.set(NR_FILTER_SOURCEGRAPHIC, in);
in = NULL; // in is now handled by FilterSlot, we should not touch it
- // TODO: loop through ALL the primitives and render them one at a time
- _primitive[0]->render(slot, paraller_trans);
+ for (int i = 0 ; i < _primitive_count ; i++) {
+ _primitive[i]->render(slot, paraller_trans);
+ }
NRPixBlock *out = slot.get(_output_slot);
// Clear the pixblock, where the output will be put
@@ -310,7 +312,7 @@ void Filter::_create_constructor_table()
if(created) return;
/* Filter effects not yet implemented are set to NULL */
- _constructor[NR_FILTER_BLEND] = NULL;
+ _constructor[NR_FILTER_BLEND] = &FilterBlend::create;
_constructor[NR_FILTER_COLORMATRIX] = NULL;
_constructor[NR_FILTER_COMPONENTTRANSFER] = NULL;
_constructor[NR_FILTER_COMPOSITE] = NULL;
diff --git a/src/sp-feblend.cpp b/src/sp-feblend.cpp
index 7448dd4ab..55c387e00 100644
--- a/src/sp-feblend.cpp
+++ b/src/sp-feblend.cpp
@@ -6,9 +6,10 @@
*/
/*
* Authors:
- * hugo Rodrigues <haa.rodrigues@gmail.com>
+ * Hugo Rodrigues <haa.rodrigues@gmail.com>
+ * Niko Kiirala <niko@kiirala.com>
*
- * Copyright (C) 2006 Hugo Rodrigues
+ * Copyright (C) 2006,2007 authors
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
@@ -17,11 +18,14 @@
# include "config.h"
#endif
+#include <string.h>
+
#include "attributes.h"
#include "svg/svg.h"
#include "sp-feblend.h"
#include "xml/repr.h"
+#include "display/nr-filter-blend.h"
/* FeBlend base class */
@@ -89,6 +93,7 @@ sp_feBlend_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *re
}
/*LOAD ATTRIBUTES FROM REPR HERE*/
+ sp_object_read_attr(object, "mode");
}
/**
@@ -101,6 +106,37 @@ sp_feBlend_release(SPObject *object)
((SPObjectClass *) feBlend_parent_class)->release(object);
}
+static NR::FilterBlendMode sp_feBlend_readmode(gchar const *value)
+{
+ if (!value) return NR::BLEND_NORMAL;
+ switch (value[0]) {
+ case 'n':
+ if (strncmp(value, "normal", 6) == 0)
+ return NR::BLEND_NORMAL;
+ break;
+ case 'm':
+ if (strncmp(value, "multiply", 8) == 0)
+ return NR::BLEND_MULTIPLY;
+ break;
+ case 's':
+ if (strncmp(value, "screen", 6) == 0)
+ return NR::BLEND_SCREEN;
+ break;
+ case 'd':
+ if (strncmp(value, "darken", 6) == 0)
+ return NR::BLEND_DARKEN;
+ break;
+ case 'l':
+ if (strncmp(value, "lighten", 7) == 0)
+ return NR::BLEND_LIGHTEN;
+ break;
+ default:
+ // do nothing by default
+ break;
+ }
+ return NR::BLEND_NORMAL;
+}
+
/**
* Sets a specific value in the SPFeBlend.
*/
@@ -112,6 +148,9 @@ sp_feBlend_set(SPObject *object, unsigned int key, gchar const *value)
switch(key) {
/*DEAL WITH SETTING ATTRIBUTES HERE*/
+ case SP_ATTR_MODE:
+ feBlend->blend_mode = sp_feBlend_readmode(value);
+ break;
default:
if (((SPObjectClass *) feBlend_parent_class)->set)
((SPObjectClass *) feBlend_parent_class)->set(object, key, value);
@@ -148,7 +187,7 @@ sp_feBlend_write(SPObject *object, Inkscape::XML::Node *repr, guint flags)
if (flags & SP_OBJECT_WRITE_EXT) {
if (repr) {
// is this sane?
- repr->mergeFrom(SP_OBJECT_REPR(object), "id");
+ // repr->mergeFrom(SP_OBJECT_REPR(object), "id");
} else {
repr = SP_OBJECT_REPR(object)->duplicate(NULL); // FIXME
}
diff --git a/src/sp-feblend.h b/src/sp-feblend.h
index dea1100a3..90ab8967f 100644
--- a/src/sp-feblend.h
+++ b/src/sp-feblend.h
@@ -7,8 +7,9 @@
/*
* Authors:
* Hugo Rodrigues <haa.rodrigues@gmail.com>
+ * Niko Kiirala <niko@kiirala.com>
*
- * Copyright (C) 2006 Hugo Rodrigues
+ * Copyright (C) 2006,2007 authors
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
@@ -16,12 +17,14 @@
#include "sp-filter.h"
#include "sp-feblend-fns.h"
+#include "display/nr-filter-blend.h"
+
/* FeBlend base class */
class SPFeBlendClass;
struct SPFeBlend : public SPFilterPrimitive {
/** BLEND ATTRIBUTES HERE */
-
+ NR::FilterBlendMode blend_mode;
};
struct SPFeBlendClass {