Code

First version of feOffset support. Contains some rendering glitches.
authorkiirala <kiirala@users.sourceforge.net>
Thu, 7 Jun 2007 15:26:34 +0000 (15:26 +0000)
committerkiirala <kiirala@users.sourceforge.net>
Thu, 7 Jun 2007 15:26:34 +0000 (15:26 +0000)
src/display/Makefile_insert
src/display/nr-arena-item.cpp
src/display/nr-filter-offset.cpp [new file with mode: 0644]
src/display/nr-filter-offset.h [new file with mode: 0644]
src/display/nr-filter-skeleton.cpp [new file with mode: 0644]
src/display/nr-filter-skeleton.h [new file with mode: 0644]
src/display/nr-filter-slot.cpp
src/display/nr-filter.cpp
src/sp-feoffset.cpp
src/sp-feoffset.h

index 95502170a22118c7841612b492b4cdb43c55a9d8..a4d7470017c9c99bf7214d2405dc4b821cd1ccf0 100644 (file)
@@ -71,6 +71,8 @@ display_libspdisplay_a_SOURCES = \
        display/nr-filter-gaussian.h    \
        display/nr-filter-blend.cpp     \
        display/nr-filter-blend.h       \
+       display/nr-filter-offset.cpp    \
+       display/nr-filter-offset.h      \
        display/nr-filter-slot.cpp      \
        display/nr-filter-slot.h        \
        display/nr-filter-types.h       \
index b7ff825d28a98f61778a8eda13b63c3697ff8090..a4fdcf5bc93fcc4fee527fde396240b7c030d324 100644 (file)
@@ -414,9 +414,10 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area
 
         /* If background access is used, save the pixblock address.
          * This address is set to NULL at the end of this block */
-        if (item->background_new
-            || (item->parent && item->parent->background_pb)) {
+        if (item->background_new) {
             item->background_pb = &ipb;
+        } else if (item->parent && item->parent->background_pb) {
+            item->background_pb = item->parent->background_pb;
         }
         ipb.visible_area = pb->visible_area;
         unsigned int state = NR_ARENA_ITEM_VIRTUAL (item, render) (ct, item, &carea, &ipb, flags);
diff --git a/src/display/nr-filter-offset.cpp b/src/display/nr-filter-offset.cpp
new file mode 100644 (file)
index 0000000..ee6741d
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * feOffset filter primitive renderer
+ *
+ * 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-offset.h"
+#include "display/nr-filter-slot.h"
+#include "libnr/nr-blit.h"
+#include "libnr/nr-matrix.h"
+#include "libnr/nr-pixblock.h"
+#include "libnr/nr-point.h"
+#include "libnr/nr-point-matrix-ops.h"
+#include "libnr/nr-rect-l.h"
+
+namespace NR {
+
+FilterOffset::FilterOffset() :
+    dx(0), dy(0)
+{}
+
+FilterPrimitive * FilterOffset::create() {
+    return new FilterOffset();
+}
+
+FilterOffset::~FilterOffset()
+{}
+
+int FilterOffset::render(FilterSlot &slot, Matrix const &trans) {
+    NRPixBlock *in = slot.get(_input);
+    NRPixBlock *out = new NRPixBlock;
+
+    Point offset(dx, dy);
+    offset *= trans;
+    offset[X] -= trans[4];
+    offset[Y] -= trans[5];
+
+    nr_pixblock_setup_fast(out, in->mode,
+                           in->area.x0, in->area.y0, in->area.x1, in->area.y1,
+                           true);
+    nr_blit_pixblock_pixblock(out, in);
+
+    out->area.x0 += static_cast<NR::ICoord>(offset[X]);
+    out->area.y0 += static_cast<NR::ICoord>(offset[Y]);
+    out->area.x1 += static_cast<NR::ICoord>(offset[X]);
+    out->area.y1 += static_cast<NR::ICoord>(offset[Y]);
+    out->visible_area = out->area;
+
+    out->empty = FALSE;
+    slot.set(_output, out);
+
+    return 0;
+}
+
+void FilterOffset::set_dx(double amount) {
+    dx = amount;
+}
+
+void FilterOffset::set_dy(double amount) {
+    dy = amount;
+}
+
+void FilterOffset::area_enlarge(NRRectL &area, Matrix const &trans)
+{
+    Point offset(dx, dy);
+    offset *= trans;
+    offset[X] -= trans[4];
+    offset[Y] -= trans[5];
+
+    area.x0 -= static_cast<NR::ICoord>(offset[X]);
+    area.x1 -= static_cast<NR::ICoord>(offset[X]);
+    area.y0 -= static_cast<NR::ICoord>(offset[Y]);
+    area.y1 -= static_cast<NR::ICoord>(offset[Y]);
+}
+
+} /* 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-offset.h b/src/display/nr-filter-offset.h
new file mode 100644 (file)
index 0000000..7c39b0e
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef __NR_FILTER_OFFSET_H__
+#define __NR_FILTER_OFFSET_H__
+
+/*
+ * feOffset filter primitive renderer
+ *
+ * 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"
+#include "libnr/nr-rect-l.h"
+
+namespace NR {
+
+class FilterOffset : public FilterPrimitive {
+public:
+    FilterOffset();
+    static FilterPrimitive *create();
+    virtual ~FilterOffset();
+
+    virtual int render(FilterSlot &slot, Matrix const &trans);
+    virtual void area_enlarge(NRRectL &area, Matrix const &trans);
+
+    void set_dx(double amount);
+    void set_dy(double amount);
+
+private:
+    double dx, dy;
+};
+
+} /* namespace NR */
+
+#endif /* __NR_FILTER_OFFSET_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
new file mode 100644 (file)
index 0000000..f595f13
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Filter primitive renderer skeleton class
+ * You can create your new filter primitive renderer by replacing
+ * all occurences of Skeleton, skeleton and SKELETON with your filter
+ * 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"
+ * nr-filter-skeleton.cpp >nr-filter-name.cpp
+ *
+ * (on one line, replace occurences of 'name' with your filter name)
+ *
+ * Remember to convert the .h file too. The sed command is same for both
+ * files.
+ *
+ * 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-skeleton.h"
+#include "display/nr-filter-slot.h"
+#include "libnr/nr-pixblock.h"
+#include "libnr/nr-matrix.h"
+
+namespace NR {
+
+FilterSkeleton::FilterSkeleton() 
+{}
+
+FilterPrimitive * FilterSkeleton::create() {
+    return new FilterSkeleton();
+}
+
+FilterSkeleton::~FilterSkeleton()
+{}
+
+int FilterSkeleton::render(FilterSlot &slot, Matrix const &trans) {
+    NRPixBlock *in = slot.get(_input);
+    NRPixBlock *out;
+
+    /* Insert rendering code here */
+
+    out->empty = FALSE;
+    slot.set(_output, out);
+
+    return 0;
+}
+
+} /* 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-skeleton.h b/src/display/nr-filter-skeleton.h
new file mode 100644 (file)
index 0000000..ae3a080
--- /dev/null
@@ -0,0 +1,57 @@
+#ifndef __NR_FILTER_SKELETON_H__
+#define __NR_FILTER_SKELETON_H__
+
+/*
+ * Filter primitive renderer skeleton class
+ * You can create your new filter primitive renderer by replacing
+ * all occurences of Skeleton, skeleton and SKELETON with your filter
+ * 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"
+ * nr-filter-skeleton.h >nr-filter-name.h
+ *
+ * (on one line, replace occurences of 'name' with your filter name)
+ *
+ * Remember to convert the .cpp file too. The sed command is same for both
+ * files.
+ *
+ * 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 {
+
+class FilterSkeleton : public FilterPrimitive {
+public:
+    FilterSkeleton();
+    static FilterPrimitive *create();
+    virtual ~FilterSkeleton();
+
+    virtual int render(FilterSlot &slot, Matrix const &trans);
+
+private:
+
+};
+
+} /* namespace NR */
+
+#endif /* __NR_FILTER_SKELETON_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 673754f1855692e02dbceabe38c362e77ca75af3..250aee10b8537b9661397d81e30cdf4b20bfe958 100644 (file)
@@ -84,6 +84,7 @@ NRPixBlock *FilterSlot::get(int slot_nr)
                     delete pb;
                     return NULL;
                 }
+                pb->empty = FALSE;
                 this->set(NR_FILTER_BACKGROUNDIMAGE, pb);
             }
         }
index 38ed3938aec2b8818573ed66c7a349e621ac00a3..33e89ac3eb3bede580cf4aa2cfc76f4ec2733dc9 100644 (file)
@@ -22,6 +22,7 @@
 #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-arena-item.h"
 #include "libnr/nr-pixblock.h"
@@ -209,6 +210,7 @@ int Filter::render(NRArenaItem const *item, NRPixBlock *pb)
             return 0;
         nr_blit_pixblock_pixblock(in, pb);
     }
+    in->empty = FALSE;
     slot.set(NR_FILTER_SOURCEGRAPHIC, in);
     in = NULL; // in is now handled by FilterSlot, we should not touch it
 
@@ -316,7 +318,7 @@ void Filter::_create_constructor_table()
     _constructor[NR_FILTER_IMAGE] = NULL;
     _constructor[NR_FILTER_MERGE] = NULL;
     _constructor[NR_FILTER_MORPHOLOGY] = NULL;
-    _constructor[NR_FILTER_OFFSET] = NULL;
+    _constructor[NR_FILTER_OFFSET] = &FilterOffset::create;
     _constructor[NR_FILTER_SPECULARLIGHTING] = NULL;
     _constructor[NR_FILTER_TILE] = NULL;
     _constructor[NR_FILTER_TURBULENCE] = NULL;
index 2980f9ef810de28983909a514fe0d48743c876d2..298d3e495981cd25e8197d16b9d24d423dd3ceff 100644 (file)
@@ -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
  */
@@ -21,7 +22,7 @@
 #include "svg/svg.h"
 #include "sp-feoffset.h"
 #include "xml/repr.h"
-
+#include "display/nr-filter-offset.h"
 
 /* FeOffset base class */
 
@@ -33,6 +34,7 @@ static void sp_feOffset_release(SPObject *object);
 static void sp_feOffset_set(SPObject *object, unsigned int key, gchar const *value);
 static void sp_feOffset_update(SPObject *object, SPCtx *ctx, guint flags);
 static Inkscape::XML::Node *sp_feOffset_write(SPObject *object, Inkscape::XML::Node *repr, guint flags);
+static void sp_feOffset_build_renderer(SPFilterPrimitive *primitive, NR::Filter *filter);
 
 static SPFilterPrimitiveClass *feOffset_parent_class;
 
@@ -61,6 +63,7 @@ static void
 sp_feOffset_class_init(SPFeOffsetClass *klass)
 {
     SPObjectClass *sp_object_class = (SPObjectClass *)klass;
+    SPFilterPrimitiveClass *sp_primitive_class = (SPFilterPrimitiveClass *)klass;
 
     feOffset_parent_class = (SPFilterPrimitiveClass*)g_type_class_peek_parent(klass);
 
@@ -69,11 +72,15 @@ sp_feOffset_class_init(SPFeOffsetClass *klass)
     sp_object_class->write = sp_feOffset_write;
     sp_object_class->set = sp_feOffset_set;
     sp_object_class->update = sp_feOffset_update;
+
+    sp_primitive_class->build_renderer = sp_feOffset_build_renderer;
 }
 
 static void
 sp_feOffset_init(SPFeOffset *feOffset)
 {
+    feOffset->dx = 0;
+    feOffset->dy = 0;
 }
 
 /**
@@ -88,7 +95,8 @@ sp_feOffset_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *r
         ((SPObjectClass *) feOffset_parent_class)->build(object, document, repr);
     }
 
-    /*LOAD ATTRIBUTES FROM REPR HERE*/
+    sp_object_read_attr(object, "dx");
+    sp_object_read_attr(object, "dy");
 }
 
 /**
@@ -101,6 +109,18 @@ sp_feOffset_release(SPObject *object)
         ((SPObjectClass *) feOffset_parent_class)->release(object);
 }
 
+double sp_feOffset_read_number(gchar const *value) {
+    char *end;
+    double ret = g_ascii_strtod(value, &end);
+    if (*end) {
+        g_warning("Unable to convert \"%s\" to number", value);
+        // We could leave this out, too. If strtod can't convert
+        // anything, it will return zero.
+        ret = 0;
+    }
+    return ret;
+}
+
 /**
  * Sets a specific value in the SPFeOffset.
  */
@@ -108,9 +128,17 @@ static void
 sp_feOffset_set(SPObject *object, unsigned int key, gchar const *value)
 {
     SPFeOffset *feOffset = SP_FEOFFSET(object);
-    (void)feOffset;
 
     switch(key) {
+        case SP_ATTR_DX:
+            feOffset->dx = sp_feOffset_read_number(value);
+            object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+            break;
+        case SP_ATTR_DY:
+            feOffset->dy = sp_feOffset_read_number(value);
+            object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+            break;
+            
        /*DEAL WITH SETTING ATTRIBUTES HERE*/
         default:
             if (((SPObjectClass *) feOffset_parent_class)->set)
@@ -148,7 +176,8 @@ sp_feOffset_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");
+            // Not. Causes coredumps.
+            // repr->mergeFrom(SP_OBJECT_REPR(object), "id");
         } else {
             repr = SP_OBJECT_REPR(object)->duplicate(NULL); // FIXME
         }
@@ -161,6 +190,23 @@ sp_feOffset_write(SPObject *object, Inkscape::XML::Node *repr, guint flags)
     return repr;
 }
 
+static void sp_feOffset_build_renderer(SPFilterPrimitive *primitive, NR::Filter *filter) {
+    g_assert(primitive != NULL);
+    g_assert(filter != NULL);
+
+    SPFeOffset *sp_offset = SP_FEOFFSET(primitive);
+
+    int primitive_n = filter->add_primitive(NR::NR_FILTER_OFFSET);
+    NR::FilterPrimitive *nr_primitive = filter->get_primitive(primitive_n);
+    NR::FilterOffset *nr_offset = dynamic_cast<NR::FilterOffset*>(nr_primitive);
+    g_assert(nr_offset != NULL);
+
+    sp_filter_primitive_renderer_common(primitive, nr_primitive);
+
+    nr_offset->set_dx(sp_offset->dx);
+    nr_offset->set_dy(sp_offset->dy);
+}
+
 
 /*
   Local Variables:
index 2eda946c2c1b9d3561ada42054bb98819d3e16f4..0427114953ce466cf1122336c8ad1f7e311938e5 100644 (file)
@@ -21,7 +21,7 @@ class SPFeOffsetClass;
 
 struct SPFeOffset : public SPFilterPrimitive {
     /** OFFSET ATTRIBUTES HERE */
-    
+    double dx, dy;
 };
 
 struct SPFeOffsetClass {