summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorFelipe Corr??a da Silva Sanches <juca@members.fsf.org>2008-02-25 05:09:02 +0000
committerjucablues <jucablues@users.sourceforge.net>2008-02-25 05:09:02 +0000
commitb9b73b9df4d0d728b5f95b18b35eb998c97ee284 (patch)
tree05cba866bbe8c5976b5cca5a11c2cd938e1feeb5 /src
parentWhitespace cleanup (diff)
downloadinkscape-b9b73b9df4d0d728b5f95b18b35eb998c97ee284.tar.gz
inkscape-b9b73b9df4d0d728b5f95b18b35eb998c97ee284.zip
svg element referenced by id part of feImage filter rendering.
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. (bzr r4844)
Diffstat (limited to 'src')
-rw-r--r--src/display/nr-filter-image.cpp78
-rw-r--r--src/display/nr-filter-image.h4
-rw-r--r--src/sp-feimage.cpp34
-rw-r--r--src/sp-feimage.h3
-rw-r--r--src/ui/dialog/filter-effects-dialog.cpp2
5 files changed, 112 insertions, 9 deletions
diff --git a/src/display/nr-filter-image.cpp b/src/display/nr-filter-image.cpp
index 78e5ef8ec..42b78fa16 100644
--- a/src/display/nr-filter-image.cpp
+++ b/src/display/nr-filter-image.cpp
@@ -10,10 +10,14 @@
* 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);
diff --git a/src/display/nr-filter-image.h b/src/display/nr-filter-image.h
index afa9f798c..42e7f089a 100644
--- a/src/display/nr-filter-image.h
+++ b/src/display/nr-filter-image.h
@@ -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;
diff --git a/src/sp-feimage.cpp b/src/sp-feimage.cpp
index 271baa591..d72435f2c 100644
--- a/src/sp-feimage.cpp
+++ b/src/sp-feimage.cpp
@@ -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);
diff --git a/src/sp-feimage.h b/src/sp-feimage.h
index cf80a3166..d66a4fb77 100644
--- a/src/sp-feimage.h
+++ b/src/sp-feimage.h
@@ -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 {
diff --git a/src/ui/dialog/filter-effects-dialog.cpp b/src/ui/dialog/filter-effects-dialog.cpp
index 3a5c28520..6e9eeedb6 100644
--- a/src/ui/dialog/filter-effects-dialog.cpp
+++ b/src/ui/dialog/filter-effects-dialog.cpp
@@ -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));