]> git.tokkee.org Git - inkscape.git/commitdiff

Code

svg element referenced by id part of feImage filter rendering.
authorjucablues <jucablues@users.sourceforge.net>
Mon, 25 Feb 2008 05:09:02 +0000 (05:09 +0000)
committerjucablues <jucablues@users.sourceforge.net>
Mon, 25 Feb 2008 05:09:02 +0000 (05:09 +0000)
This commit introduces some known bugs. I will fill a bug report about it, so that we don't forget it.

Nominally they are:

* seems to leak memory. I haven't found out how. Needs review.
* it works when you create and use the filter, but it crashes when trying to open a file that already contains a
filter using feImage referencing an svgelement.

src/display/nr-filter-image.cpp
src/display/nr-filter-image.h
src/sp-feimage.cpp
src/sp-feimage.h
src/ui/dialog/filter-effects-dialog.cpp

index 78e5ef8ecf7741e4729b4ad342875f0f4127166f..42b78fa16ad2ec4e244d59b973a17cc14d933b89 100644 (file)
  * Released under GNU GPL, read the file 'COPYING' for more information
  */
 #include "document.h"
+#include "sp-item.h"
+#include "display/nr-arena.h"
 #include "display/nr-arena-item.h"
 #include "display/nr-filter.h"
 #include "display/nr-filter-image.h"
 #include "display/nr-filter-units.h"
+#include "libnr/nr-matrix.h"
+#include "libnr/nr-rect-l.h"
 
 namespace NR {
 
@@ -36,6 +40,64 @@ FilterImage::~FilterImage()
 int FilterImage::render(FilterSlot &slot, FilterUnits const &units) {
     if (!feImageHref) return 0;
 
+    NRPixBlock* pb;
+    bool free_pb_on_exit = false;
+
+    if(from_element){
+        if (!SVGElem) return 0;
+        
+        // prep the document
+        sp_document_ensure_up_to_date(document);
+        NRArena* arena = NRArena::create();
+        unsigned const key = sp_item_display_key_new(1);
+        NRArenaItem* ai = sp_item_invoke_show(SVGElem, arena, key, SP_ITEM_SHOW_DISPLAY);
+        if (!ai) {
+            g_warning("feImage renderer: error creating NRArenaItem for SVG Element");
+            g_free(arena);
+            return 0;
+        }
+        pb = new NRPixBlock;
+        free_pb_on_exit = true;
+        
+        Matrix identity(1.0, 0.0,
+                   0.0, 1.0,
+                   0.0, 0.0);
+        NR::Maybe<NR::Rect> area = SVGElem->getBounds(identity);
+        
+        NRRectL rect;
+        rect.x0=area->min()[NR::X];
+        rect.x1=area->max()[NR::X];
+        rect.y0=area->min()[NR::Y];
+        rect.y1=area->max()[NR::Y];
+
+        width = (int)(rect.x1-rect.x0);
+        height = (int)(rect.y1-rect.y0);
+
+        if (image_pixbuf) g_free(image_pixbuf);
+        image_pixbuf = g_new(unsigned char, 4 * width * height);
+        memset(image_pixbuf, 0x00, 4 * width * height);
+
+        NRGC gc(NULL);
+        /* Update to renderable state */
+        double sf = 1.0;
+        NRMatrix t;
+        nr_matrix_set_scale(&t, sf, sf);
+        nr_arena_item_set_transform(ai, &t);
+        nr_matrix_set_identity(&gc.transform);
+        nr_arena_item_invoke_update( ai, NULL, &gc,
+                                             NR_ARENA_ITEM_STATE_ALL,
+                                             NR_ARENA_ITEM_STATE_NONE );
+        nr_pixblock_setup_extern(pb, NR_PIXBLOCK_MODE_R8G8B8A8N,
+                              (int)rect.x0, (int)rect.y0, (int)rect.x1, (int)rect.y1,
+                              image_pixbuf, 4 * width, FALSE, FALSE );
+
+        nr_arena_item_invoke_render(NULL, ai, &rect, pb, NR_ARENA_ITEM_RENDER_NO_CACHE);
+
+        nr_arena_item_unref(ai);
+        nr_object_unref((NRObject *) arena);
+    }
+
+
     if (!image_pixbuf){
         try {
             gchar *fullname = feImageHref;
@@ -116,13 +178,21 @@ int FilterImage::render(FilterSlot &slot, FilterUnits const &units) {
             coordx = ( indexX >= 0 ? int( indexX ) : -1 );
             coordy = ( indexY >= 0 ? int( indexY ) : -1 );
             if (coordx >= 0 && coordx < width && coordy >= 0 && coordy < height){
-                out_data[4*((x - x0)+w*(y - y0))] = (unsigned char) image_pixbuf[3*coordx + rowstride*coordy]; //Red
-                out_data[4*((x - x0)+w*(y - y0)) + 1] = (unsigned char) image_pixbuf[3*coordx + rowstride*coordy + 1]; //Green
-                out_data[4*((x - x0)+w*(y - y0)) + 2] = (unsigned char) image_pixbuf[3*coordx + rowstride*coordy + 2]; //Blue
-                out_data[4*((x - x0)+w*(y - y0)) + 3] = 255; //Alpha
+                if (from_element){
+                    out_data[4*((x - x0)+w*(y - y0))] = (unsigned char) image_pixbuf[4*(coordx + width*coordy)]; //Red
+                    out_data[4*((x - x0)+w*(y - y0)) + 1] = (unsigned char) image_pixbuf[4*(coordx + width*coordy) + 1]; //Green
+                    out_data[4*((x - x0)+w*(y - y0)) + 2] = (unsigned char) image_pixbuf[4*(coordx + width*coordy) + 2]; //Blue
+                    out_data[4*((x - x0)+w*(y - y0)) + 3] = (unsigned char) image_pixbuf[4*(coordx + width*coordy) + 3]; //Alpha
+                } else {
+                    out_data[4*((x - x0)+w*(y - y0))] = (unsigned char) image_pixbuf[3*coordx + rowstride*coordy]; //Red
+                    out_data[4*((x - x0)+w*(y - y0)) + 1] = (unsigned char) image_pixbuf[3*coordx + rowstride*coordy + 1]; //Green
+                    out_data[4*((x - x0)+w*(y - y0)) + 2] = (unsigned char) image_pixbuf[3*coordx + rowstride*coordy + 2]; //Blue
+                    out_data[4*((x - x0)+w*(y - y0)) + 3] = 255; //Alpha
+                }
             }
         }
     }
+    if (free_pb_on_exit) nr_pixblock_release(pb);
 
     out->empty = FALSE;
     slot.set(_output, out);
index afa9f798c87b3d8b5a9d92e9a8cb72ffffad8a83..42e7f089aca77d25fc84117595b969d002f109a7 100644 (file)
@@ -16,6 +16,7 @@
 #include "display/nr-filter-slot.h"
 #include "display/nr-filter-units.h"
 #include <gtkmm.h>
+#include "sp-item.h"
 
 namespace NR {
 
@@ -30,6 +31,9 @@ public:
     void set_document( SPDocument *document );
     void set_href(const gchar *href);
     void set_region(SVGLength x, SVGLength y, SVGLength width, SVGLength height);
+    bool from_element;
+    SPItem* SVGElem;
+
 private:
     SPDocument *document;
     gchar *feImageHref;
index 271baa5914a9a978a33b4307541aa013812e5050..d72435f2c5415cc77b1895fabcd2384504cd73da 100644 (file)
@@ -18,7 +18,8 @@
 #ifdef HAVE_CONFIG_H
 # include "config.h"
 #endif
-
+#include "uri.h"
+#include "uri-references.h"
 #include "attributes.h"
 #include "svg/svg.h"
 #include "sp-feimage.h"
@@ -130,14 +131,36 @@ sp_feImage_set(SPObject *object, unsigned int key, gchar const *value)
 {
     SPFeImage *feImage = SP_FEIMAGE(object);
     (void)feImage;
-
+    Inkscape::URI* SVGElem_uri;
+    Inkscape::URIReference* SVGElemRef;
     switch(key) {
        /*DEAL WITH SETTING ATTRIBUTES HERE*/
        case SP_ATTR_XLINK_HREF:
            if (feImage->href) g_free(feImage->href);
            feImage->href = (value) ? g_strdup (value) : NULL;
-           object->requestModified(SP_OBJECT_MODIFIED_FLAG);
-            break;
+            if (!feImage->href) return;
+            try{
+                SVGElem_uri = new Inkscape::URI(feImage->href);
+                SVGElemRef = new Inkscape::URIReference(feImage->document);
+                feImage->from_element = true;
+                SVGElemRef->attach(*SVGElem_uri);
+                feImage->SVGElem = SP_ITEM(SVGElemRef->getObject());
+                
+                g_free(SVGElem_uri);
+                g_free(SVGElemRef);
+                //TODO: maybe keeping SVGElemRef we can observe changes to the
+                // referenced object and trigger updates of the filtered object
+                object->requestModified(SP_OBJECT_MODIFIED_FLAG);
+                break;
+            }
+            catch(const Inkscape::UnsupportedURIException & e)
+            {
+                feImage->from_element = false;
+                g_warning("caught Inkscape::UnsupportedURIException in sp_feImage_set");
+                break;
+            }
+
+
         case SP_ATTR_X:
             feImage->x.readOrUnset(value);
             object->requestModified(SP_OBJECT_MODIFIED_FLAG);
@@ -215,6 +238,9 @@ static void sp_feImage_build_renderer(SPFilterPrimitive *primitive, NR::Filter *
     g_assert(nr_image != NULL);
 
     sp_filter_primitive_renderer_common(primitive, nr_primitive);
+
+    nr_image->from_element = sp_image->from_element;
+    nr_image->SVGElem = sp_image->SVGElem;
     nr_image->set_region(sp_image->x, sp_image->y, sp_image->width, sp_image->height);
     nr_image->set_href(sp_image->href);
     nr_image->set_document(sp_image->document);
index cf80a31666fd15ef60fde8f9703004ec60da0b80..d66a4fb770594608fc6241213512df86a077fd42 100644 (file)
@@ -17,6 +17,7 @@
 #include "sp-filter.h"
 #include "sp-feimage-fns.h"
 #include "svg/svg-length.h"
+#include "sp-item.h"
 
 /* FeImage base class */
 class SPFeImageClass;
@@ -26,6 +27,8 @@ struct SPFeImage : public SPFilterPrimitive {
     gchar *href;
     SVGLength x, y, height, width;
     SPDocument *document;
+    bool from_element;
+    SPItem* SVGElem;
 };
 
 struct SPFeImageClass {
index 3a5c285208dcf024d0c56d538869c3d4adc38f88..6e9eeedb6a934232fe37d3f5fb4d36cbbda04e7f 100644 (file)
@@ -609,7 +609,7 @@ public:
     {
         pack_start(_entry, false, false);
         pack_start(_fromFile, false, false);
-        //pack_start(_fromSVGElement, false, false);
+        pack_start(_fromSVGElement, false, false);
 
         _fromFile.set_label(_("Image File"));
         _fromFile.signal_clicked().connect(sigc::mem_fun(*this, &FileOrElementChooser::select_file));