summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 68991a7)
raw | patch | inline | side by side (parent: 68991a7)
author | kiirala <kiirala@users.sourceforge.net> | |
Thu, 26 Jul 2007 11:38:36 +0000 (11:38 +0000) | ||
committer | kiirala <kiirala@users.sourceforge.net> | |
Thu, 26 Jul 2007 11:38:36 +0000 (11:38 +0000) |
src/Makefile_insert | patch | blob | history | |
src/display/Makefile_insert | patch | blob | history | |
src/display/nr-filter-merge.cpp | [new file with mode: 0644] | patch | blob |
src/display/nr-filter-merge.h | [new file with mode: 0644] | patch | blob |
src/display/nr-filter.cpp | patch | blob | history | |
src/sp-femerge.cpp | patch | blob | history | |
src/sp-femerge.h | patch | blob | history | |
src/sp-femergenode.cpp | [new file with mode: 0644] | patch | blob |
src/sp-femergenode.h | [new file with mode: 0644] | patch | blob |
src/sp-object-repr.cpp | patch | blob | history |
diff --git a/src/Makefile_insert b/src/Makefile_insert
index 548a4933491ffcfcd19c7eab85e3fbc9e9ddcbe1..d57dd5774c06d2e4547e7fa6c16e311e8e616a2a 100644 (file)
--- a/src/Makefile_insert
+++ b/src/Makefile_insert
sp-feimage-fns.h \
sp-femerge.cpp sp-femerge.h \
sp-femerge-fns.h \
+ sp-femergenode.cpp sp-femergenode.h \
sp-femorphology.cpp sp-femorphology.h \
sp-femorphology-fns.h \
sp-feoffset.cpp sp-feoffset.h \
index 624733a42f2efbf3b9e7183f3186f541ec33dc82..1713dc75114dcf11071c82fa081a769c156272e7 100644 (file)
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
--- /dev/null
@@ -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
--- /dev/null
@@ -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 :
index f09573eb4694e5d4eb7c17b365d5596c692ef26e..95867363b8956b90b46e175584e5681205dc1ecb 100644 (file)
#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"
_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;
diff --git a/src/sp-femerge.cpp b/src/sp-femerge.cpp
index 2b262db0d2cfadbac7cae03ea6952b889d41735c..dfa664941d27263eb55225ae1ddf3ce5c8abd889 100644 (file)
--- a/src/sp-femerge.cpp
+++ b/src/sp-femerge.cpp
#include "attributes.h"
#include "svg/svg.h"
-#include "sp-femerge.h"
#include "xml/repr.h"
+#include "sp-femerge.h"
+#include "sp-femergenode.h"
+#include "display/nr-filter-merge.h"
/* FeMerge base class */
static void sp_feMerge_set(SPObject *object, unsigned int key, gchar const *value);
static void sp_feMerge_update(SPObject *object, SPCtx *ctx, guint flags);
static Inkscape::XML::Node *sp_feMerge_write(SPObject *object, Inkscape::XML::Node *repr, guint flags);
+static void sp_feMerge_build_renderer(SPFilterPrimitive *primitive, NR::Filter *filter);
static SPFilterPrimitiveClass *feMerge_parent_class;
sp_feMerge_class_init(SPFeMergeClass *klass)
{
SPObjectClass *sp_object_class = (SPObjectClass *)klass;
+ SPFilterPrimitiveClass *sp_primitive_class = (SPFilterPrimitiveClass *)klass;
feMerge_parent_class = (SPFilterPrimitiveClass*)g_type_class_peek_parent(klass);
sp_object_class->write = sp_feMerge_write;
sp_object_class->set = sp_feMerge_set;
sp_object_class->update = sp_feMerge_update;
+
+ sp_primitive_class->build_renderer = sp_feMerge_build_renderer;
}
static void
static void
sp_feMerge_update(SPObject *object, SPCtx *ctx, guint flags)
{
- if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG |
- SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) {
-
- /* do something to trigger redisplay, updates? */
-
+ if (flags & SP_OBJECT_MODIFIED_FLAG) {
+ object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
if (((SPObjectClass *) feMerge_parent_class)->update) {
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
}
return repr;
}
+static void sp_feMerge_build_renderer(SPFilterPrimitive *primitive, NR::Filter *filter) {
+ g_assert(primitive != NULL);
+ g_assert(filter != NULL);
+
+ SPFeMerge *sp_merge = SP_FEMERGE(primitive);
+
+ int primitive_n = filter->add_primitive(NR::NR_FILTER_MERGE);
+ NR::FilterPrimitive *nr_primitive = filter->get_primitive(primitive_n);
+ NR::FilterMerge *nr_merge = dynamic_cast<NR::FilterMerge*>(nr_primitive);
+ g_assert(nr_merge != NULL);
+
+ sp_filter_primitive_renderer_common(primitive, nr_primitive);
+
+ SPObject *input = primitive->children;
+ int in_nr = 0;
+ while (input) {
+ if (SP_IS_FEMERGENODE(input)) {
+ SPFeMergeNode *node = SP_FEMERGENODE(input);
+ nr_merge->set_input(in_nr, node->input);
+ in_nr++;
+ }
+ input = input->next;
+ }
+}
+
/*
Local Variables:
diff --git a/src/sp-femerge.h b/src/sp-femerge.h
index 015f2e33c415f435a1fdcba4d8c6159e170f5102..f83697fca9d914dfc1cdf4d6afcafb0327d6180f 100644 (file)
--- a/src/sp-femerge.h
+++ b/src/sp-femerge.h
class SPFeMergeClass;
struct SPFeMerge : public SPFilterPrimitive {
- /** MERGE ATTRIBUTES HERE */
};
diff --git a/src/sp-femergenode.cpp b/src/sp-femergenode.cpp
--- /dev/null
+++ b/src/sp-femergenode.cpp
@@ -0,0 +1,177 @@
+#define __SP_FEMERGENODE_CPP__
+
+/** \file
+ * feMergeNode implementation. A feMergeNode contains the name of one
+ * input image for feMerge.
+ */
+/*
+ * Authors:
+ * Kees Cook <kees@outflux.net>
+ * Niko Kiirala <niko@kiirala.com>
+ *
+ * Copyright (C) 2004,2007 authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "attributes.h"
+#include "xml/repr.h"
+#include "sp-femergenode.h"
+#include "sp-femerge.h"
+
+static void sp_feMergeNode_class_init(SPFeMergeNodeClass *klass);
+static void sp_feMergeNode_init(SPFeMergeNode *skeleton);
+
+static void sp_feMergeNode_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr);
+static void sp_feMergeNode_release(SPObject *object);
+static void sp_feMergeNode_set(SPObject *object, unsigned int key, gchar const *value);
+static void sp_feMergeNode_update(SPObject *object, SPCtx *ctx, guint flags);
+static Inkscape::XML::Node *sp_feMergeNode_write(SPObject *object, Inkscape::XML::Node *repr, guint flags);
+
+static SPObjectClass *feMergeNode_parent_class;
+
+GType
+sp_feMergeNode_get_type()
+{
+ static GType feMergeNode_type = 0;
+
+ if (!feMergeNode_type) {
+ GTypeInfo feMergeNode_info = {
+ sizeof(SPFeMergeNodeClass),
+ NULL, NULL,
+ (GClassInitFunc) sp_feMergeNode_class_init,
+ NULL, NULL,
+ sizeof(SPFeMergeNode),
+ 16,
+ (GInstanceInitFunc) sp_feMergeNode_init,
+ NULL, /* value_table */
+ };
+ feMergeNode_type = g_type_register_static(SP_TYPE_OBJECT, "SPFeMergeNode", &feMergeNode_info, (GTypeFlags)0);
+ }
+ return feMergeNode_type;
+}
+
+static void
+sp_feMergeNode_class_init(SPFeMergeNodeClass *klass)
+{
+ //GObjectClass *gobject_class = (GObjectClass *)klass;
+ SPObjectClass *sp_object_class = (SPObjectClass *)klass;
+
+ feMergeNode_parent_class = (SPObjectClass*)g_type_class_peek_parent(klass);
+
+ sp_object_class->build = sp_feMergeNode_build;
+ sp_object_class->release = sp_feMergeNode_release;
+ sp_object_class->write = sp_feMergeNode_write;
+ sp_object_class->set = sp_feMergeNode_set;
+ sp_object_class->update = sp_feMergeNode_update;
+}
+
+static void
+sp_feMergeNode_init(SPFeMergeNode *feMergeNode)
+{
+ feMergeNode->input = NR::NR_FILTER_SLOT_NOT_SET;
+}
+
+/**
+ * Reads the Inkscape::XML::Node, and initializes SPFeMergeNode variables. For this to get called,
+ * our name must be associated with a repr via "sp_object_type_register". Best done through
+ * sp-object-repr.cpp's repr_name_entries array.
+ */
+static void
+sp_feMergeNode_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr)
+{
+ sp_object_read_attr(object, "in");
+}
+
+/**
+ * Drops any allocated memory.
+ */
+static void
+sp_feMergeNode_release(SPObject *object)
+{
+ /* deal with our children and our selves here */
+
+ if (((SPObjectClass *) feMergeNode_parent_class)->release)
+ ((SPObjectClass *) feMergeNode_parent_class)->release(object);
+}
+
+/**
+ * Sets a specific value in the SPFeMergeNode.
+ */
+static void
+sp_feMergeNode_set(SPObject *object, unsigned int key, gchar const *value)
+{
+ SPFeMergeNode *feMergeNode = SP_FEMERGENODE(object);
+ SPFeMerge *parent = SP_FEMERGE(object->parent);
+
+ if (key == SP_ATTR_IN) {
+ int input = sp_filter_primitive_read_in(parent, value);
+ if (input != feMergeNode->input) {
+ feMergeNode->input = input;
+ object->requestModified(SP_OBJECT_MODIFIED_FLAG);
+ }
+ }
+
+ /* See if any parents need this value. */
+ if (((SPObjectClass *) feMergeNode_parent_class)->set) {
+ ((SPObjectClass *) feMergeNode_parent_class)->set(object, key, value);
+ }
+}
+
+/**
+ * Receives update notifications.
+ */
+static void
+sp_feMergeNode_update(SPObject *object, SPCtx *ctx, guint flags)
+{
+ //SPFeMergeNode *feMergeNode = SP_FEMERGENODE(object);
+
+ if (flags & SP_OBJECT_MODIFIED_FLAG) {
+ object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+ }
+
+ if (((SPObjectClass *) feMergeNode_parent_class)->update) {
+ ((SPObjectClass *) feMergeNode_parent_class)->update(object, ctx, flags);
+ }
+}
+
+/**
+ * Writes its settings to an incoming repr object, if any.
+ */
+static Inkscape::XML::Node *
+sp_feMergeNode_write(SPObject *object, Inkscape::XML::Node *repr, guint flags)
+{
+ //SPFeMergeNode *feMergeNode = SP_FEMERGENODE(object);
+
+ // Inkscape-only object, not copied during an "plain SVG" dump:
+ if (flags & SP_OBJECT_WRITE_EXT) {
+ if (repr) {
+ // is this sane?
+ repr->mergeFrom(SP_OBJECT_REPR(object), "id");
+ } else {
+ repr = SP_OBJECT_REPR(object)->duplicate(NULL); // FIXME
+ }
+ }
+
+ if (((SPObjectClass *) feMergeNode_parent_class)->write) {
+ ((SPObjectClass *) feMergeNode_parent_class)->write(object, repr, flags);
+ }
+
+ return repr;
+}
+
+
+/*
+ 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/sp-femergenode.h b/src/sp-femergenode.h
--- /dev/null
+++ b/src/sp-femergenode.h
@@ -0,0 +1,49 @@
+#ifndef SP_FEMERGENODE_H_SEEN
+#define SP_FEMERGENODE_H_SEEN
+
+/** \file
+ * feMergeNode implementation. A feMergeNode stores information about one
+ * input image for feMerge filter primitive.
+ */
+/*
+ * Authors:
+ * Kees Cook <kees@outflux.net>
+ * Niko Kiirala <niko@kiirala.com>
+ *
+ * Copyright (C) 2004,2007 authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "sp-object.h"
+
+#define SP_TYPE_FEMERGENODE (sp_feMergeNode_get_type())
+#define SP_FEMERGENODE(o) (G_TYPE_CHECK_INSTANCE_CAST((o), SP_TYPE_FEMERGENODE, SPFeMergeNode))
+#define SP_IS_FEMERGENODE(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), SP_TYPE_FEMERGENODE))
+
+class SPFeMergeNode;
+class SPFeMergeNodeClass;
+
+struct SPFeMergeNode : public SPObject {
+ int input;
+};
+
+struct SPFeMergeNodeClass {
+ SPObjectClass parent_class;
+};
+
+GType sp_feMergeNode_get_type();
+
+
+#endif /* !SP_FEMERGENODE_H_SEEN */
+
+/*
+ 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/sp-object-repr.cpp b/src/sp-object-repr.cpp
index 4e417e29434a6902864276e64584dbe8987df9c0..f05455e84f39fa9b73519ee846f99d4cf9408bd1 100644 (file)
--- a/src/sp-object-repr.cpp
+++ b/src/sp-object-repr.cpp
#include "sp-fespotlight.h"
#include "sp-fetile.h"
#include "sp-feturbulence.h"
+#include "sp-femergenode.h"
enum NameType { REPR_NAME, SODIPODI_TYPE };
static unsigned const N_NAME_TYPES = SODIPODI_TYPE + 1;
{ "svg:feSpotLight", SP_TYPE_FESPOTLIGHT },
{ "svg:feTile", SP_TYPE_FETILE },
{ "svg:feTurbulence", SP_TYPE_FETURBULENCE },
+ { "svg:feMergeNode", SP_TYPE_FEMERGENODE },
{ "svg:image", SP_TYPE_IMAGE },
{ "svg:line", SP_TYPE_LINE },
{ "svg:linearGradient", SP_TYPE_LINEARGRADIENT },