summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKrzysztof Kosi??ski <tweenk.pl@gmail.com>2010-07-29 00:56:18 +0000
committerKrzysztof KosiƄski <tweenk.pl@gmail.com>2010-07-29 00:56:18 +0000
commitf014bfbb52135cfa486a22269e1a7770d0713a22 (patch)
tree1cc575f01e48b353abab4c82a74413a4eb0e0750 /src
parentAdd OpenMP IF clauses to filter templates, instead of modifying num_threads (diff)
downloadinkscape-f014bfbb52135cfa486a22269e1a7770d0713a22.tar.gz
inkscape-f014bfbb52135cfa486a22269e1a7770d0713a22.zip
First half of image filter (display from external image)
(bzr r9508.1.38)
Diffstat (limited to 'src')
-rw-r--r--src/display/nr-filter-image.cpp122
-rw-r--r--src/display/nr-filter-image.h10
-rw-r--r--src/display/nr-filter-slot.h1
3 files changed, 118 insertions, 15 deletions
diff --git a/src/display/nr-filter-image.cpp b/src/display/nr-filter-image.cpp
index 5dec64dc7..eda19afcd 100644
--- a/src/display/nr-filter-image.cpp
+++ b/src/display/nr-filter-image.cpp
@@ -11,6 +11,7 @@
*/
#include "document.h"
#include "sp-item.h"
+#include "display/cairo-utils.h"
#include "display/nr-arena.h"
#include "display/nr-arena-item.h"
#include "display/nr-filter.h"
@@ -23,11 +24,12 @@
namespace Inkscape {
namespace Filters {
-FilterImage::FilterImage() :
- SVGElem(0),
- document(0),
- feImageHref(0),
- image_pixbuf(0)
+FilterImage::FilterImage()
+ : SVGElem(0)
+ , document(0)
+ , feImageHref(0)
+ , image_surface(0)
+ , broken_ref(false)
{ }
FilterPrimitive * FilterImage::create() {
@@ -40,17 +42,18 @@ FilterImage::~FilterImage()
g_free(feImageHref);
}
-/*
void FilterImage::render_cairo(FilterSlot &slot)
{
if (!feImageHref)
return;
- cairo_surface_t *input = slot.getcairo(_input);
+ //cairo_surface_t *input = slot.getcairo(_input);
if (from_element) {
if (!SVGElem) return;
+ return; //not ready yet
+/*
// prep the document
// TODO: do not recreate the rendering tree every time
sp_document_ensure_up_to_date(document);
@@ -69,7 +72,7 @@ void FilterImage::render_cairo(FilterSlot &slot)
Geom::Rect area = *optarea;
Geom::Matrix itrans = slot.get_units().get_matrix_display2pb();
- NRRectL const &slot_area = slot.get_units().get_slot_area();
+ NRRectL const &slot_area = slot.get_slot_area();
NRRectL rect;
rect.x0 = floor(area->left());
rect.x1 = ceil(area->right());
@@ -95,10 +98,103 @@ void FilterImage::render_cairo(FilterSlot &slot)
slot.set(_output, out);
cairo_surface_destroy(out);
- return;
+ return;*/
+ }
+
+ if (!image && !broken_ref) {
+ broken_ref = true;
+ try {
+ /* TODO: If feImageHref is absolute, then use that (preferably handling the
+ * case that it's not a file URI). Otherwise, go up the tree looking
+ * for an xml:base attribute, and use that as the base URI for resolving
+ * the relative feImageHref URI. Otherwise, if document && document->base,
+ * then use that as the base URI. Otherwise, use feImageHref directly
+ * (i.e. interpreting it as relative to our current working directory).
+ * (See http://www.w3.org/TR/xmlbase/#resolution .) */
+ gchar *fullname = feImageHref;
+ if ( !g_file_test( fullname, G_FILE_TEST_EXISTS ) ) {
+ // Try to load from relative postion combined with document base
+ if( document ) {
+ fullname = g_build_filename( document->base, feImageHref, NULL );
+ }
+ }
+ if ( !g_file_test( fullname, G_FILE_TEST_EXISTS ) ) {
+ // Should display Broken Image png.
+ g_warning("FilterImage::render: Can not find: %s", feImageHref );
+ }
+ image = Gdk::Pixbuf::create_from_file(fullname);
+ if( fullname != feImageHref ) g_free( fullname );
+ }
+ catch (const Glib::FileError & e)
+ {
+ g_warning("caught Glib::FileError in FilterImage::render %i", e.code() );
+ return;
+ }
+ catch (const Gdk::PixbufError & e)
+ {
+ g_warning("Gdk::PixbufError in FilterImage::render: %i", e.code() );
+ return;
+ }
+ if ( !image ) return;
+
+ broken_ref = false;
+
+ bool has_alpha = image->get_has_alpha();
+ if (!has_alpha) {
+ image = image->add_alpha(false, 0, 0, 0);
+ }
+
+ // Native size of image
+ //width = image->get_width();
+ //height = image->get_height();
+ //rowstride = image->get_rowstride();
+
+ convert_pixbuf_normal_to_argb32(image->gobj());
+
+ image_surface = cairo_image_surface_create_for_data(image->get_pixels(),
+ CAIRO_FORMAT_ARGB32, image->get_width(), image->get_height(), image->get_rowstride());
}
-}*/
+ NRRectL const &sa = slot.get_slot_area();
+ cairo_surface_t *out = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
+ sa.x1 - sa.x0, sa.y1 - sa.y0);
+
+ cairo_t *ct = cairo_create(out);
+ cairo_translate(ct, -sa.x0, -sa.y0);
+ // now ct is in pb coordinates
+ ink_cairo_transform(ct, slot.get_units().get_matrix_primitiveunits2pb());
+ // now ct is in the coordinates of feImageX etc.
+
+ // Get the object bounding box in user coordinates. Image is placed with respect to box.
+ // Array values: 0: width; 3: height; 4: -x; 5: -y.
+ Geom::Matrix object_bbox = slot.get_units().get_matrix_user2filterunits();
+
+ // feImage is suppose to use the same parameters as a normal SVG image.
+ // If a width or height is set to zero, the image is not suppose to be displayed.
+ // This does not seem to be what Firefox or Opera does, nor does the W3C displacement
+ // filter test expect this behavior. If the width and/or height are zero, we use
+ // the width and height of the object bounding box.
+ if( feImageWidth == 0 ) feImageWidth = object_bbox[0];
+ if( feImageHeight == 0 ) feImageHeight = object_bbox[3];
+
+ double scaleX = feImageWidth / image->get_width();
+ double scaleY = feImageHeight / image->get_height();
+
+ cairo_translate(ct, feImageX, feImageY);
+ cairo_scale(ct, scaleX, scaleY);
+ cairo_set_source_surface(ct, image_surface, 0, 0);
+ cairo_paint(ct);
+ cairo_destroy(ct);
+
+ slot.set(_output, out);
+}
+
+bool FilterImage::can_handle_affine(Geom::Matrix const &)
+{
+ return true;
+}
+
+#if 0
int FilterImage::render(FilterSlot &slot, FilterUnits const &units) {
if (!feImageHref) return 0;
@@ -279,10 +375,16 @@ int FilterImage::render(FilterSlot &slot, FilterUnits const &units) {
slot.set(_output, out);
return 0;
}
+#endif
void FilterImage::set_href(const gchar *href){
if (feImageHref) g_free (feImageHref);
feImageHref = (href) ? g_strdup (href) : NULL;
+
+ if (image_surface) {
+ cairo_surface_destroy(image_surface);
+ }
+ image.reset();
}
void FilterImage::set_document(SPDocument *doc){
diff --git a/src/display/nr-filter-image.h b/src/display/nr-filter-image.h
index f3565ef9f..1f7064196 100644
--- a/src/display/nr-filter-image.h
+++ b/src/display/nr-filter-image.h
@@ -27,8 +27,8 @@ public:
static FilterPrimitive *create();
virtual ~FilterImage();
- virtual int render(FilterSlot &slot, FilterUnits const &units);
- virtual FilterTraits get_input_traits();
+ virtual void render_cairo(FilterSlot &slot);
+ virtual bool can_handle_affine(Geom::Matrix const &);
void set_document( SPDocument *document );
void set_href(const gchar *href);
void set_region(SVGLength x, SVGLength y, SVGLength width, SVGLength height);
@@ -38,11 +38,11 @@ public:
private:
SPDocument *document;
gchar *feImageHref;
- guint8* image_pixbuf;
Glib::RefPtr<Gdk::Pixbuf> image;
- int width, height, rowstride;
+ cairo_surface_t *image_surface;
+ //int width, height, rowstride;
float feImageX,feImageY,feImageWidth,feImageHeight;
- bool has_alpha;
+ bool broken_ref;
};
} /* namespace Filters */
diff --git a/src/display/nr-filter-slot.h b/src/display/nr-filter-slot.h
index a9fac61d9..57f3f1054 100644
--- a/src/display/nr-filter-slot.h
+++ b/src/display/nr-filter-slot.h
@@ -79,6 +79,7 @@ public:
FilterUnits const &get_units() const { return _units; }
NRRectL const &get_slot_area() const { return _slot_area; }
+ NRRectL const &get_sg_area() const { return *_source_graphic_area; }
private:
typedef std::map<int, cairo_surface_t *> SlotMap;