Code

Offline work done during weekend:
authorJucaBlues <JucaBlues@users.sourceforge.net>
Mon, 11 Feb 2008 01:48:14 +0000 (01:48 +0000)
committerJucaBlues <JucaBlues@users.sourceforge.net>
Mon, 11 Feb 2008 01:48:14 +0000 (01:48 +0000)
* handle fefuncR, fefuncG, fefuncB and fefuncA nodes
* implement fecomponenttransfer renderer
** identity and gamma modes render perfectly
** linear and table modes are rendering with very slight imperfections

This commit still mantains feComponentTransfer out of UI (still not implemented)

src/Makefile_insert
src/display/nr-filter-component-transfer.cpp
src/display/nr-filter-component-transfer.h
src/helper-fns.h
src/sp-fecomponenttransfer-funcnode.cpp [new file with mode: 0644]
src/sp-fecomponenttransfer-funcnode.h [new file with mode: 0644]
src/sp-fecomponenttransfer.cpp
src/sp-fecomponenttransfer.h
src/sp-object-repr.cpp
src/ui/dialog/filter-effects-dialog.cpp

index 196d5e562bd9f4419219dcad524e1184e222ab8a..d37cb9b59ba0d71bd01771cd77158356bcc85f2f 100644 (file)
@@ -165,6 +165,7 @@ libinkpre_a_SOURCES =       \
        sp-fecolormatrix.cpp sp-fecolormatrix.h \
        sp-fecolormatrix-fns.h  \
        sp-fecomponenttransfer.cpp sp-fecomponenttransfer.h     \
+       sp-fecomponenttransfer-funcnode.cpp sp-fecomponenttransfer-funcnode.h   \
        sp-fecomponenttransfer-fns.h    \
        sp-fecomposite.cpp sp-fecomposite.h     \
        sp-fecomposite-fns.h    \
index 9b20034022998ceabff5c74d13c0e8964b7c9c20..1edb3ac98fcca609f2bed031d64e1e4d441bc013 100644 (file)
 
 #include "display/nr-filter-component-transfer.h"
 #include "display/nr-filter-units.h"
+#include "display/nr-filter-utils.h"
+#include "libnr/nr-pixblock.h"
+#include "libnr/nr-blit.h"
+#include <math.h>
 
 namespace NR {
 
 FilterComponentTransfer::FilterComponentTransfer()
 {
-    g_warning("FilterComponentTransfer::render not implemented.");
 }
 
 FilterPrimitive * FilterComponentTransfer::create() {
@@ -28,25 +31,92 @@ FilterComponentTransfer::~FilterComponentTransfer()
 
 int FilterComponentTransfer::render(FilterSlot &slot, FilterUnits const &/*units*/) {
     NRPixBlock *in = slot.get(_input);
+
     if (!in) {
         g_warning("Missing source image for feComponentTransfer (in=%d)", _input);
         return 1;
     }
 
-    NRPixBlock *out = new NRPixBlock;
+    int x0=in->area.x0;
+    int x1=in->area.x1;
+    int y0=in->area.y0;
+    int y1=in->area.y1;
 
-    nr_pixblock_setup_fast(out, in->mode,
-                           in->area.x0, in->area.y0, in->area.x1, in->area.y1,
-                           true);
+    NRPixBlock *out = new NRPixBlock;
+    nr_pixblock_setup_fast(out, NR_PIXBLOCK_MODE_R8G8B8A8N, x0, y0, x1, y1, true);
+
+    // this primitive is defined for non-premultiplied RGBA values,
+    // thus convert them to that format before blending
+    if (in->mode != NR_PIXBLOCK_MODE_R8G8B8A8N) {
+        NRPixBlock *original_in = in;
+        in = new NRPixBlock;
+        nr_pixblock_setup_fast(in, NR_PIXBLOCK_MODE_R8G8B8A8N,
+                               original_in->area.x0, original_in->area.y0,
+                               original_in->area.x1, original_in->area.y1,
+                               false);
+        nr_blit_pixblock_pixblock(in, original_in);
+    }
 
     unsigned char *in_data = NR_PIXBLOCK_PX(in);
     unsigned char *out_data = NR_PIXBLOCK_PX(out);
 
-//IMPLEMENT ME!
-    g_warning("Renderer for feComponentTransfer is not implemented.");
     (void)in_data;
     (void)out_data;
 
+    int size = 4 * (y1-y0) * (x1-x0);
+    int i;
+
+    for (int color=0;color<4;color++){
+        int _vsize = tableValues[color].size();
+        std::vector<gdouble> _tableValues = tableValues[color];
+        double _intercept = intercept[color];
+        double _slope = slope[color];
+        double _amplitude = amplitude[color];
+        double _exponent = exponent[color];
+        double _offset = offset[color];        
+        switch(type[color]){
+            case COMPONENTTRANSFER_TYPE_IDENTITY:
+                for(i=color;i<size;i+=4){
+                    out_data[i]=in_data[i];
+                }
+                break;
+            case COMPONENTTRANSFER_TYPE_TABLE:
+                if (_vsize==0){
+                    for(i=color;i<size;i+=4){
+                        out_data[i]=in_data[i];
+                    }
+                } else {
+                    for(i=color;i<size;i+=4){
+                        int k = (int)(((_vsize-1) * (double)in_data[i])/256);
+                        double dx = ((_vsize-1) * (double)in_data[i])/256 - k;
+                        out_data[i] = CLAMP_D_TO_U8(256 * (_tableValues[k] + dx * (_tableValues[k+1] - _tableValues[k]) ));
+                    }
+                }
+                break;
+            case COMPONENTTRANSFER_TYPE_DISCRETE:
+                if (_vsize==0){
+                    for(i=color;i<size;i+=4){
+                        out_data[i] = in_data[i];
+                    }
+                } else {
+                    for(i=color;i<size;i+=4){
+                        out_data[i] = CLAMP_D_TO_U8(256 * _tableValues[(int)((_vsize-1)*(double)in_data[i]/256)] );
+                    }
+                }
+                break;
+            case COMPONENTTRANSFER_TYPE_LINEAR:
+                for(i=color;i<size;i+=4){
+                    out_data[i] = CLAMP_D_TO_U8(256 * (_slope * (double)in_data[i]/256 + _intercept));
+                }
+                break;
+            case COMPONENTTRANSFER_TYPE_GAMMA:
+                for(i=color;i<size;i+=4){
+                    out_data[i] = CLAMP_D_TO_U8(256 * (_amplitude * pow((double)in_data[i]/256, _exponent) + _offset));
+                }
+                break;
+        }
+    }
+
     out->empty = FALSE;
     slot.set(_output, out);
     return 0;
@@ -56,35 +126,6 @@ void FilterComponentTransfer::area_enlarge(NRRectL &/*area*/, Matrix const &/*tr
 {
 }
 
-void FilterComponentTransfer::set_type(FilterComponentTransferType t){
-    type = t;
-}
-
-void FilterComponentTransfer::set_slope(double s){
-        slope = s;
-}
-
-void FilterComponentTransfer::set_tableValues(std::vector<double> &tv){
-        tableValues = tv;
-}
-
-
-void FilterComponentTransfer::set_intercept(double i){
-        intercept = i;
-}
-
-void FilterComponentTransfer::set_amplitude(double a){
-        amplitude = a;
-}
-
-void FilterComponentTransfer::set_exponent(double e){
-        exponent = e;
-}
-
-void FilterComponentTransfer::set_offset(double o){
-        offset = o;
-}
-
 } /* namespace NR */
 
 /*
index 30b793777abf271d41d36cd4670198ae6777bdec..ae08d6f290c60e55a8f13f3622731b1389694db8 100644 (file)
@@ -37,22 +37,13 @@ public:
     virtual int render(FilterSlot &slot, FilterUnits const &units);
     virtual void area_enlarge(NRRectL &area, Matrix const &trans);
 
-    void set_type(FilterComponentTransferType t);    
-    void set_tableValues(std::vector<gdouble>& tv);
-    void set_slope(double s);
-    void set_intercept(double i);
-    void set_amplitude(double a);
-    void set_exponent(double e);
-    void set_offset(double o);
-
-private:
-    FilterComponentTransferType type;
-    std::vector<gdouble> tableValues;
-    double slope;
-    double intercept;
-    double amplitude;
-    double exponent;
-    double offset;
+    FilterComponentTransferType type[4];
+    std::vector<gdouble> tableValues[4];
+    double slope[4];
+    double intercept[4];
+    double amplitude[4];
+    double exponent[4];
+    double offset[4];
 };
 
 } /* namespace NR */
index b1a1e37f05f744bcf689db179165a9d33bb7627b..635aefd79525ddee3554a308ca15f5e394678191 100644 (file)
@@ -61,6 +61,16 @@ inline std::vector<gdouble> helperfns_read_vector(const gchar* value, int size){
         return v;
 }
 
+inline std::vector<gdouble> helperfns_read_vector(const gchar* value){
+        std::vector<gdouble> v;
+        std::istringstream is(value);
+        gdouble d;
+        while (is >> d){
+            v.push_back(d);
+        }
+        return v;
+}
+
 #endif /* !SEEN_HELPER_FNS_H */
 
 /*
diff --git a/src/sp-fecomponenttransfer-funcnode.cpp b/src/sp-fecomponenttransfer-funcnode.cpp
new file mode 100644 (file)
index 0000000..84f7197
--- /dev/null
@@ -0,0 +1,344 @@
+#define __SP_FEFUNCNODE_CPP__
+
+/** \file
+ * SVG <funcR>, <funcG>, <funcB> and <funcA> implementations.
+ */
+/*
+ * Authors:
+ *   Hugo Rodrigues <haa.rodrigues@gmail.com>
+ *   Niko Kiirala <niko@kiirala.com>
+ *   Felipe CorrĂȘa da Silva Sanches <felipe.sanches@gmail.com>
+ * 
+ * Copyright (C) 2006, 2007, 2008 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+
+#include "attributes.h"
+#include "document.h"
+#include "sp-fecomponenttransfer.h"
+#include "sp-fecomponenttransfer-funcnode.h"
+#include "display/nr-filter-component-transfer.h"
+#include "xml/repr.h"
+#include "helper-fns.h"
+
+#define SP_MACROS_SILENT
+#include "macros.h"
+
+/* FeFuncNode class */
+
+static void sp_fefuncnode_class_init(SPFeFuncNodeClass *klass);
+static void sp_fefuncnode_init(SPFeFuncNode *fefuncnode);
+
+static void sp_fefuncnode_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr);
+static void sp_fefuncnode_release(SPObject *object);
+static void sp_fefuncnode_set(SPObject *object, unsigned int key, gchar const *value);
+static void sp_fefuncnode_update(SPObject *object, SPCtx *ctx, guint flags);
+static Inkscape::XML::Node *sp_fefuncnode_write(SPObject *object, Inkscape::XML::Node *repr, guint flags);
+
+static SPObjectClass *feFuncNode_parent_class;
+
+GType
+sp_fefuncR_get_type()
+{
+    static GType fefuncnode_type = 0;
+
+    if (!fefuncnode_type) {
+        GTypeInfo fefuncnode_info = {
+            sizeof(SPFeFuncNodeClass),
+            NULL, NULL,
+            (GClassInitFunc) sp_fefuncnode_class_init,
+            NULL, NULL,
+            sizeof(SPFeFuncNode),
+            16,
+            (GInstanceInitFunc) sp_fefuncnode_init,
+            NULL,    /* value_table */
+        };
+        fefuncnode_type = g_type_register_static(SP_TYPE_OBJECT, "SPFeFuncR", &fefuncnode_info, (GTypeFlags)0);
+    }
+    return fefuncnode_type;
+}
+
+GType
+sp_fefuncG_get_type()
+{
+    static GType fefuncnode_type = 0;
+
+    if (!fefuncnode_type) {
+        GTypeInfo fefuncnode_info = {
+            sizeof(SPFeFuncNodeClass),
+            NULL, NULL,
+            (GClassInitFunc) sp_fefuncnode_class_init,
+            NULL, NULL,
+            sizeof(SPFeFuncNode),
+            16,
+            (GInstanceInitFunc) sp_fefuncnode_init,
+            NULL,    /* value_table */
+        };
+        fefuncnode_type = g_type_register_static(SP_TYPE_OBJECT, "SPFeFuncG", &fefuncnode_info, (GTypeFlags)0);
+    }
+    return fefuncnode_type;
+}
+
+GType
+sp_fefuncB_get_type()
+{
+    static GType fefuncnode_type = 0;
+
+    if (!fefuncnode_type) {
+        GTypeInfo fefuncnode_info = {
+            sizeof(SPFeFuncNodeClass),
+            NULL, NULL,
+            (GClassInitFunc) sp_fefuncnode_class_init,
+            NULL, NULL,
+            sizeof(SPFeFuncNode),
+            16,
+            (GInstanceInitFunc) sp_fefuncnode_init,
+            NULL,    /* value_table */
+        };
+        fefuncnode_type = g_type_register_static(SP_TYPE_OBJECT, "SPFeFuncB", &fefuncnode_info, (GTypeFlags)0);
+    }
+    return fefuncnode_type;
+}
+
+GType
+sp_fefuncA_get_type()
+{
+    static GType fefuncnode_type = 0;
+
+    if (!fefuncnode_type) {
+        GTypeInfo fefuncnode_info = {
+            sizeof(SPFeFuncNodeClass),
+            NULL, NULL,
+            (GClassInitFunc) sp_fefuncnode_class_init,
+            NULL, NULL,
+            sizeof(SPFeFuncNode),
+            16,
+            (GInstanceInitFunc) sp_fefuncnode_init,
+            NULL,    /* value_table */
+        };
+        fefuncnode_type = g_type_register_static(SP_TYPE_OBJECT, "SPFeFuncA", &fefuncnode_info, (GTypeFlags)0);
+    }
+    return fefuncnode_type;
+}
+
+static void
+sp_fefuncnode_class_init(SPFeFuncNodeClass *klass)
+{
+
+    SPObjectClass *sp_object_class = (SPObjectClass *)klass;
+
+    feFuncNode_parent_class = (SPObjectClass*)g_type_class_peek_parent(klass);
+
+    sp_object_class->build = sp_fefuncnode_build;
+    sp_object_class->release = sp_fefuncnode_release;
+    sp_object_class->write = sp_fefuncnode_write;
+    sp_object_class->set = sp_fefuncnode_set;
+    sp_object_class->update = sp_fefuncnode_update;
+}
+
+static void
+sp_fefuncnode_init(SPFeFuncNode *fefuncnode)
+{
+    fefuncnode->type = NR::COMPONENTTRANSFER_TYPE_IDENTITY;
+    //fefuncnode->tableValues = NULL;
+    fefuncnode->slope = 1;
+    fefuncnode->intercept = 0;
+    fefuncnode->amplitude = 1;
+    fefuncnode->exponent = 1;
+    fefuncnode->offset = 0;
+}
+
+/**
+ * Reads the Inkscape::XML::Node, and initializes SPDistantLight 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_fefuncnode_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr)
+{
+    if (((SPObjectClass *) feFuncNode_parent_class)->build) {
+        ((SPObjectClass *) feFuncNode_parent_class)->build(object, document, repr);
+    }
+
+    //Read values of key attributes from XML nodes into object.
+    sp_object_read_attr(object, "type");
+    sp_object_read_attr(object, "tableValues");
+    sp_object_read_attr(object, "slope");
+    sp_object_read_attr(object, "intercept");
+    sp_object_read_attr(object, "amplitude");
+    sp_object_read_attr(object, "exponent");
+    sp_object_read_attr(object, "offset");
+    
+
+//is this necessary?
+    sp_document_add_resource(document, "fefuncnode", object); //maybe feFuncR, fefuncG, feFuncB and fefuncA ?
+}
+
+/**
+ * Drops any allocated memory.
+ */
+static void
+sp_fefuncnode_release(SPObject *object)
+{
+    //SPFeFuncNode *fefuncnode = SP_FEFUNCNODE(object);
+
+    if (SP_OBJECT_DOCUMENT(object)) {
+        /* Unregister ourselves */
+        sp_document_remove_resource(SP_OBJECT_DOCUMENT(object), "fefuncnode", SP_OBJECT(object));
+    }
+
+//TODO: release resources here
+}
+
+static NR::FilterComponentTransferType sp_feComponenttransfer_read_type(gchar const *value){
+    if (!value) return NR::COMPONENTTRANSFER_TYPE_ERROR; //type attribute is REQUIRED.
+    switch(value[0]){
+        case 'i':
+            if (strncmp(value, "identity", 8) == 0) return NR::COMPONENTTRANSFER_TYPE_IDENTITY;
+            break;
+        case 't':
+            if (strncmp(value, "table", 5) == 0) return NR::COMPONENTTRANSFER_TYPE_TABLE;
+            break;
+        case 'd':
+            if (strncmp(value, "discrete", 8) == 0) return NR::COMPONENTTRANSFER_TYPE_DISCRETE;
+            break;
+        case 'l':
+            if (strncmp(value, "linear", 6) == 0) return NR::COMPONENTTRANSFER_TYPE_LINEAR;
+            break;
+        case 'g':
+            if (strncmp(value, "gamma", 5) == 0) return NR::COMPONENTTRANSFER_TYPE_GAMMA;
+            break;
+    }
+    return NR::COMPONENTTRANSFER_TYPE_ERROR; //type attribute is REQUIRED.
+}
+
+/**
+ * Sets a specific value in the SPFeFuncNode.
+ */
+static void
+sp_fefuncnode_set(SPObject *object, unsigned int key, gchar const *value)
+{
+    SPFeFuncNode *feFuncNode = SP_FEFUNCNODE(object);
+    NR::FilterComponentTransferType type;
+    double read_num;
+    switch(key) {
+        case SP_ATTR_TYPE:
+            type = sp_feComponenttransfer_read_type(value);
+            if(type != feFuncNode->type) {
+                feFuncNode->type = type;
+                object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+            }
+            break;
+        case SP_ATTR_TABLEVALUES:
+            if (value){
+                feFuncNode->tableValues = helperfns_read_vector(value);
+                object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+            }
+            break;
+        case SP_ATTR_SLOPE:
+            read_num = helperfns_read_number(value);
+            if (read_num != feFuncNode->slope) {
+                feFuncNode->slope = read_num;
+                object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+            }
+            break;
+        case SP_ATTR_INTERCEPT:
+            read_num = helperfns_read_number(value);
+            if (read_num != feFuncNode->intercept) {
+                feFuncNode->intercept = read_num;
+                object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+            }
+            break;
+        case SP_ATTR_AMPLITUDE:
+            read_num = helperfns_read_number(value);
+            if (read_num != feFuncNode->amplitude) {
+                feFuncNode->amplitude = read_num;
+                object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+            }
+            break;
+        case SP_ATTR_EXPONENT:
+            read_num = helperfns_read_number(value);
+            if (read_num != feFuncNode->exponent) {
+                feFuncNode->exponent = read_num;
+                object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+            }
+            break;
+        case SP_ATTR_OFFSET:
+            read_num = helperfns_read_number(value);
+            if (read_num != feFuncNode->offset) {
+                feFuncNode->offset = read_num;
+                object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+            }
+            break;
+        default:
+            if (((SPObjectClass *) feFuncNode_parent_class)->set)
+                ((SPObjectClass *) feFuncNode_parent_class)->set(object, key, value);
+            break;
+    }
+}
+
+/**
+ *  * Receives update notifications.
+ *   */
+static void
+sp_fefuncnode_update(SPObject *object, SPCtx *ctx, guint flags)
+{
+    SPFeFuncNode *feFuncNode = SP_FEFUNCNODE(object);
+    (void)feFuncNode;
+
+    if (flags & SP_OBJECT_MODIFIED_FLAG) {
+        /* do something to trigger redisplay, updates? */
+        //TODO
+        //sp_object_read_attr(object, "azimuth");
+        //sp_object_read_attr(object, "elevation");
+    }
+
+    if (((SPObjectClass *) feFuncNode_parent_class)->update) {
+        ((SPObjectClass *) feFuncNode_parent_class)->update(object, ctx, flags);
+    }
+}
+
+/**
+ * Writes its settings to an incoming repr object, if any.
+ */
+static Inkscape::XML::Node *
+sp_fefuncnode_write(SPObject *object, Inkscape::XML::Node *repr, guint flags)
+{
+    SPFeFuncNode *fefuncnode = SP_FEFUNCNODE(object);
+
+    if (!repr) {
+        repr = SP_OBJECT_REPR(object)->duplicate(NULL); // FIXME
+    }
+
+    /*
+TODO: I'm not sure what to do here...
+
+    if (fefuncnode->azimuth_set)
+        sp_repr_set_css_double(repr, "azimuth", fefuncnode->azimuth);
+    if (fefuncnode->elevation_set)
+        sp_repr_set_css_double(repr, "elevation", fefuncnode->elevation);*/
+
+    if (((SPObjectClass *) feFuncNode_parent_class)->write) {
+        ((SPObjectClass *) feFuncNode_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-fecomponenttransfer-funcnode.h b/src/sp-fecomponenttransfer-funcnode.h
new file mode 100644 (file)
index 0000000..2f0b2fc
--- /dev/null
@@ -0,0 +1,72 @@
+#ifndef SP_FECOMPONENTTRANSFER_FUNCNODE_H_SEEN
+#define SP_FECOMPONENTTRANSFER_FUNCNODE_H_SEEN
+
+/** \file
+ * SVG <filter> implementation, see sp-filter.cpp.
+ */
+/*
+ * Authors:
+ *   Hugo Rodrigues <haa.rodrigues@gmail.com>
+ *   Niko Kiirala <niko@kiirala.com>
+ *   Felipe CorrĂȘa da Silva Sanches <felipe.sanches@gmail.com>
+ *
+ * Copyright (C) 2006,2007 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "sp-object.h"
+#include "display/nr-filter-component-transfer.h"
+
+#define SP_TYPE_FEFUNCR (sp_fefuncR_get_type())
+#define SP_TYPE_FEFUNCG (sp_fefuncG_get_type())
+#define SP_TYPE_FEFUNCB (sp_fefuncB_get_type())
+#define SP_TYPE_FEFUNCA (sp_fefuncA_get_type())
+
+#define SP_IS_FEFUNCR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FEFUNCR))
+#define SP_IS_FEFUNCG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FEFUNCG))
+#define SP_IS_FEFUNCB(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FEFUNCB))
+#define SP_IS_FEFUNCA(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FEFUNCA))
+
+#define SP_FEFUNCNODE(obj) (SP_IS_FEFUNCR(obj) ? G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FEFUNCR, SPFeFuncNode) : (SP_IS_FEFUNCG(obj) ? G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FEFUNCG, SPFeFuncNode) : (SP_IS_FEFUNCB(obj) ? G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FEFUNCB, SPFeFuncNode):(SP_IS_FEFUNCA(obj) ? G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FEFUNCA, SPFeFuncNode): NULL))))
+
+#define SP_FEFUNCNODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FEFUNCNODE, SPFeFuncNodeClass))
+
+#define SP_IS_FEFUNCNODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FEFUNCNODE))
+
+/* Component Transfer funcNode class */
+
+class SPFeFuncNode;
+class SPFeFuncNodeClass;
+
+struct SPFeFuncNode : public SPObject {
+    NR::FilterComponentTransferType type;
+    std::vector<double> tableValues;
+    double slope;
+    double intercept;
+    double amplitude;
+    double exponent;
+    double offset;
+};
+
+struct SPFeFuncNodeClass {
+    SPObjectClass parent_class;
+};
+
+GType sp_fefuncR_get_type();
+GType sp_fefuncG_get_type();
+GType sp_fefuncB_get_type();
+GType sp_fefuncA_get_type();
+
+#endif /* !SP_FECOMPONENTTRANSFER_FUNCNODE_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 :
index f9ecaa47ca87ee16d97f53839082e65ce9052497..0b00546391dc3268abf3b0b135dca059723f3a27 100644 (file)
 
 #include <string.h>
 
+#include "document.h"
 #include "attributes.h"
 #include "svg/svg.h"
 #include "sp-fecomponenttransfer.h"
+#include "sp-fecomponenttransfer-funcnode.h"
 #include "xml/repr.h"
-#include "display/nr-filter-component-transfer.h"
+//#include "display/nr-filter-component-transfer.h"
 
 /* FeComponentTransfer base class */
 
@@ -34,8 +36,10 @@ static void sp_feComponentTransfer_build(SPObject *object, SPDocument *document,
 static void sp_feComponentTransfer_release(SPObject *object);
 static void sp_feComponentTransfer_set(SPObject *object, unsigned int key, gchar const *value);
 static void sp_feComponentTransfer_update(SPObject *object, SPCtx *ctx, guint flags);
+static void sp_feComponentTransfer_build_renderer(SPFilterPrimitive *primitive, NR::Filter *filter);
+static void sp_feComponentTransfer_remove_child(SPObject *object, Inkscape::XML::Node *child);
+static void sp_feComponentTransfer_child_added(SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *ref);
 static Inkscape::XML::Node *sp_feComponentTransfer_write(SPObject *object, Inkscape::XML::Node *repr, guint flags);
-
 static SPFilterPrimitiveClass *feComponentTransfer_parent_class;
 
 GType
@@ -63,7 +67,7 @@ static void
 sp_feComponentTransfer_class_init(SPFeComponentTransferClass *klass)
 {
     SPObjectClass *sp_object_class = (SPObjectClass *)klass;
-
+    SPFilterPrimitiveClass *sp_primitive_class = (SPFilterPrimitiveClass *)klass;
     feComponentTransfer_parent_class = (SPFilterPrimitiveClass*)g_type_class_peek_parent(klass);
 
     sp_object_class->build = sp_feComponentTransfer_build;
@@ -71,20 +75,15 @@ sp_feComponentTransfer_class_init(SPFeComponentTransferClass *klass)
     sp_object_class->write = sp_feComponentTransfer_write;
     sp_object_class->set = sp_feComponentTransfer_set;
     sp_object_class->update = sp_feComponentTransfer_update;
+    sp_object_class->child_added = sp_feComponentTransfer_child_added;
+    sp_object_class->remove_child = sp_feComponentTransfer_remove_child;
+
+    sp_primitive_class->build_renderer = sp_feComponentTransfer_build_renderer;
 }
 
 static void
 sp_feComponentTransfer_init(SPFeComponentTransfer *feComponentTransfer)
-{
-    //Setting default values:
-//TODO: tableValues = "" (empty list);
-    feComponentTransfer->slope = 1;
-    feComponentTransfer->intercept = 0;
-    feComponentTransfer->amplitude = 1;
-    feComponentTransfer->exponent = 1;
-    feComponentTransfer->offset = 0;
-//    feComponentTransfer->type = NR::COMPONENTTRANSFER_TYPE_ERROR;
-}
+{}
 
 /**
  * Reads the Inkscape::XML::Node, and initializes SPFeComponentTransfer variables.  For this to get called,
@@ -99,13 +98,63 @@ sp_feComponentTransfer_build(SPObject *object, SPDocument *document, Inkscape::X
     }
 
     /*LOAD ATTRIBUTES FROM REPR HERE*/
-    sp_object_read_attr(object, "type");
-    sp_object_read_attr(object, "tableValues");
-    sp_object_read_attr(object, "slope");
-    sp_object_read_attr(object, "intercept");
-    sp_object_read_attr(object, "amplitude");
-    sp_object_read_attr(object, "exponent");
-    sp_object_read_attr(object, "offset");
+
+    //do we need this?
+    sp_document_add_resource(document, "feComponentTransfer", object);
+}
+
+static void sp_feComponentTransfer_children_modified(SPFeComponentTransfer *sp_componenttransfer)
+{
+    if (sp_componenttransfer->renderer) {
+        SPObject* node = sp_componenttransfer->children;
+        for(;node;node=node->next){
+            int i=4;
+            if (SP_IS_FEFUNCR(node)) i=0;
+            if (SP_IS_FEFUNCG(node)) i=1;
+            if (SP_IS_FEFUNCB(node)) i=2;
+            if (SP_IS_FEFUNCA(node)) i=3;
+            if (i==4) break;
+            sp_componenttransfer->renderer->type[i] = ((SPFeFuncNode *) node)->type;
+            sp_componenttransfer->renderer->tableValues[i] = ((SPFeFuncNode *) node)->tableValues;
+            sp_componenttransfer->renderer->slope[i] = ((SPFeFuncNode *) node)->slope;
+            sp_componenttransfer->renderer->intercept[i] = ((SPFeFuncNode *) node)->intercept;
+            sp_componenttransfer->renderer->amplitude[i] = ((SPFeFuncNode *) node)->amplitude;
+            sp_componenttransfer->renderer->exponent[i] = ((SPFeFuncNode *) node)->exponent;
+            sp_componenttransfer->renderer->offset[i] = ((SPFeFuncNode *) node)->offset;
+        }
+    }
+}
+
+/**
+ * Callback for child_added event.
+ */
+static void
+sp_feComponentTransfer_child_added(SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *ref)
+{
+    g_warning("child_added");
+    SPFeComponentTransfer *f = SP_FECOMPONENTTRANSFER(object);
+
+    if (((SPObjectClass *) feComponentTransfer_parent_class)->child_added)
+        (* ((SPObjectClass *) feComponentTransfer_parent_class)->child_added)(object, child, ref);
+
+    sp_feComponentTransfer_children_modified(f);
+    object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+}
+            
+
+/**
+ * Callback for remove_child event.
+ */
+static void
+sp_feComponentTransfer_remove_child(SPObject *object, Inkscape::XML::Node *child)
+{   
+    SPFeComponentTransfer *f = SP_FECOMPONENTTRANSFER(object);
+
+    if (((SPObjectClass *) feComponentTransfer_parent_class)->remove_child)
+        (* ((SPObjectClass *) feComponentTransfer_parent_class)->remove_child)(object, child);   
+
+    sp_feComponentTransfer_children_modified(f);
+    object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
 }
 
 /**
@@ -118,28 +167,6 @@ sp_feComponentTransfer_release(SPObject *object)
         ((SPObjectClass *) feComponentTransfer_parent_class)->release(object);
 }
 
-static NR::FilterComponentTransferType sp_feComponenttransfer_read_type(gchar const *value){
-    if (!value) return NR::COMPONENTTRANSFER_TYPE_ERROR; //type attribute is REQUIRED.
-    switch(value[0]){
-        case 'i':
-            if (strncmp(value, "identity", 8) == 0) return NR::COMPONENTTRANSFER_TYPE_IDENTITY;
-            break;
-        case 't':
-            if (strncmp(value, "table", 5) == 0) return NR::COMPONENTTRANSFER_TYPE_TABLE;
-            break;
-        case 'd':
-            if (strncmp(value, "discrete", 8) == 0) return NR::COMPONENTTRANSFER_TYPE_DISCRETE;
-            break;
-        case 'l':
-            if (strncmp(value, "linear", 6) == 0) return NR::COMPONENTTRANSFER_TYPE_LINEAR;
-            break;
-        case 'g':
-            if (strncmp(value, "gamma", 5) == 0) return NR::COMPONENTTRANSFER_TYPE_GAMMA;
-            break;
-    }
-    return NR::COMPONENTTRANSFER_TYPE_ERROR; //type attribute is REQUIRED.
-}
-
 /**
  * Sets a specific value in the SPFeComponentTransfer.
  */
@@ -149,15 +176,7 @@ sp_feComponentTransfer_set(SPObject *object, unsigned int key, gchar const *valu
     SPFeComponentTransfer *feComponentTransfer = SP_FECOMPONENTTRANSFER(object);
     (void)feComponentTransfer;
 
-    NR::FilterComponentTransferType type;
     switch(key) {
-        case SP_ATTR_TYPE:
-            type = sp_feComponenttransfer_read_type(value);
-            if(type != feComponentTransfer->type) {
-                feComponentTransfer->type = type;
-                object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
-            }
-            break;
        /*DEAL WITH SETTING ATTRIBUTES HERE*/
         default:
             if (((SPObjectClass *) feComponentTransfer_parent_class)->set)
@@ -208,6 +227,23 @@ sp_feComponentTransfer_write(SPObject *object, Inkscape::XML::Node *repr, guint
     return repr;
 }
 
+static void sp_feComponentTransfer_build_renderer(SPFilterPrimitive *primitive, NR::Filter *filter) {
+    g_assert(primitive != NULL);
+    g_assert(filter != NULL);
+
+    SPFeComponentTransfer *sp_componenttransfer = SP_FECOMPONENTTRANSFER(primitive);
+
+    int primitive_n = filter->add_primitive(NR::NR_FILTER_COMPONENTTRANSFER);
+    NR::FilterPrimitive *nr_primitive = filter->get_primitive(primitive_n);
+    NR::FilterComponentTransfer *nr_componenttransfer = dynamic_cast<NR::FilterComponentTransfer*>(nr_primitive);
+    g_assert(nr_componenttransfer != NULL);
+
+    sp_componenttransfer->renderer = nr_componenttransfer;
+    sp_filter_primitive_renderer_common(primitive, nr_primitive);
+
+
+    sp_feComponentTransfer_children_modified(sp_componenttransfer);    //do we need it?!
+}
 
 /*
   Local Variables:
index 2a0fa01ed41ae577c99e59327326cbc4839333df..f32512c7a5be6a8fd6583718bba1c4d477657a4b 100644 (file)
@@ -23,13 +23,8 @@ class SPFeComponentTransferClass;
 
 struct SPFeComponentTransfer : public SPFilterPrimitive {
     /** COMPONENTTRANSFER ATTRIBUTES HERE */
-    NR::FilterComponentTransferType type;
-    std::vector<double> tableValues;
-    double slope;
-    double intercept;
-    double amplitude;
-    double exponent;
-    double offset;
+
+    NR::FilterComponentTransfer *renderer;
 };
 
 struct SPFeComponentTransferClass {
index 5fa36d7b589884692431abe5fafe082ca66aab07..57e9ef986627465e5b4041bd3682777a27355270 100644 (file)
@@ -52,6 +52,7 @@
 #include "sp-feblend.h"
 #include "sp-fecolormatrix.h"
 #include "sp-fecomponenttransfer.h"
+#include "sp-fecomponenttransfer-funcnode.h"
 #include "sp-fecomposite.h"
 #include "sp-feconvolvematrix.h"
 #include "sp-fediffuselighting.h"
@@ -148,6 +149,10 @@ populate_dtables()
         { "svg:feDistantLight", SP_TYPE_FEDISTANTLIGHT },
         { "svg:feDisplacementMap", SP_TYPE_FEDISPLACEMENTMAP },
         { "svg:feFlood", SP_TYPE_FEFLOOD },
+        { "svg:feFuncR", SP_TYPE_FEFUNCR },
+        { "svg:feFuncG", SP_TYPE_FEFUNCG },
+        { "svg:feFuncB", SP_TYPE_FEFUNCB },
+        { "svg:feFuncA", SP_TYPE_FEFUNCA },
         { "svg:feGaussianBlur", SP_TYPE_GAUSSIANBLUR },
         { "svg:feImage", SP_TYPE_FEIMAGE },
         { "svg:feMerge", SP_TYPE_FEMERGE },
index 12cb29bef5012fe3f3341f2dcd768282dd8f4ce7..9856c63b73a208e0f7fcf2b9077cc317dc0c915b 100644 (file)
@@ -2345,19 +2345,21 @@ void FilterEffectsDialog::update_settings_sensitivity()
     _k3->set_sensitive(use_k);
     _k4->set_sensitive(use_k);
 
+// Component transfer not yet implemented
+/*
     if(SP_IS_FECOMPONENTTRANSFER(prim)) {
         SPFeComponentTransfer* ct = SP_FECOMPONENTTRANSFER(prim);
         const bool linear = ct->type == COMPONENTTRANSFER_TYPE_LINEAR;
         const bool gamma = ct->type == COMPONENTTRANSFER_TYPE_GAMMA;
 
-        // Component transfer not yet implemented
-        /*_ct_table->set_sensitive(ct->type == COMPONENTTRANSFER_TYPE_TABLE || ct->type == COMPONENTTRANSFER_TYPE_DISCRETE);
+        _ct_table->set_sensitive(ct->type == COMPONENTTRANSFER_TYPE_TABLE || ct->type == COMPONENTTRANSFER_TYPE_DISCRETE);
         _ct_slope->set_sensitive(linear);
         _ct_intercept->set_sensitive(linear);
         _ct_amplitude->set_sensitive(gamma);
         _ct_exponent->set_sensitive(gamma);
-        _ct_offset->set_sensitive(gamma);*/
+        _ct_offset->set_sensitive(gamma);
     }
+*/
 }
 
 void FilterEffectsDialog::update_color_matrix()