summaryrefslogtreecommitdiffstats
path: root/src/display
diff options
context:
space:
mode:
authorMarkus Engel <markus.engel@tum.de>2013-09-19 17:32:15 +0000
committerMarkus Engel <markus.engel@tum.de>2013-09-19 17:32:15 +0000
commit658a60b2ffdb7ed361b3c3b57d62efd419f7ba47 (patch)
tree7f0f76347c27e59a784b4a3af990af7b247c5b41 /src/display
parentAdded gpl notice (diff)
parentDo not require a new layer for clipping paths in the Cairo renderer. (diff)
downloadinkscape-658a60b2ffdb7ed361b3c3b57d62efd419f7ba47.tar.gz
inkscape-658a60b2ffdb7ed361b3c3b57d62efd419f7ba47.zip
Merged from trunk (r12544).
(bzr r11608.1.126)
Diffstat (limited to 'src/display')
-rw-r--r--src/display/cairo-utils.cpp539
-rw-r--r--src/display/cairo-utils.h70
-rw-r--r--src/display/drawing-image.cpp64
-rw-r--r--src/display/drawing-image.h6
-rw-r--r--src/display/drawing-item.cpp8
-rw-r--r--src/display/drawing-item.h4
-rw-r--r--src/display/drawing-shape.cpp4
-rw-r--r--src/display/drawing-text.cpp6
-rw-r--r--src/display/nr-filter-image.cpp69
-rw-r--r--src/display/nr-filter-image.h6
-rw-r--r--src/display/nr-filter.cpp27
-rw-r--r--src/display/nr-filter.h6
12 files changed, 559 insertions, 250 deletions
diff --git a/src/display/cairo-utils.cpp b/src/display/cairo-utils.cpp
index 755553033..451f0b509 100644
--- a/src/display/cairo-utils.cpp
+++ b/src/display/cairo-utils.cpp
@@ -15,6 +15,8 @@
#include "display/cairo-utils.h"
#include <stdexcept>
+#include <glib/gstdio.h>
+#include <glibmm/fileutils.h>
#include <2geom/pathvector.h>
#include <2geom/bezier-curve.h>
#include <2geom/hvlinesegment.h>
@@ -28,6 +30,8 @@
#include "helper/geom-curves.h"
#include "display/cairo-templates.h"
+static void ink_cairo_pixbuf_cleanup(guchar *, void *);
+
/**
* Key for cairo_surface_t to keep track of current color interpolation value
* Only the address of the structure is used, it is never initialized. See:
@@ -116,6 +120,380 @@ Cairo::RefPtr<CairoContext> CairoContext::create(Cairo::RefPtr<Cairo::Surface> c
return ret;
}
+
+/* The class below implement the following hack:
+ *
+ * The pixels formats of Cairo and GdkPixbuf are different.
+ * GdkPixbuf accesses pixels as bytes, alpha is not premultiplied,
+ * and successive bytes of a single pixel contain R, G, B and A components.
+ * Cairo accesses pixels as 32-bit ints, alpha is premultiplied,
+ * and each int contains as 0xAARRGGBB, accessed with bitwise operations.
+ *
+ * In other words, on a little endian system, a GdkPixbuf will contain:
+ * char *data = "rgbargbargba...."
+ * int *data = { 0xAABBGGRR, 0xAABBGGRR, 0xAABBGGRR, ... }
+ * while a Cairo image surface will contain:
+ * char *data = "bgrabgrabgra...."
+ * int *data = { 0xAARRGGBB, 0xAARRGGBB, 0xAARRGGBB, ... }
+ *
+ * It is possible to convert between these two formats (almost) losslessly.
+ * Some color information from partially transparent regions of the image
+ * is lost, but the result when displaying this image will remain the same.
+ *
+ * The class allows interoperation between GdkPixbuf
+ * and Cairo surfaces without creating a copy of the image.
+ * This is implemented by creating a GdkPixbuf and a Cairo image surface
+ * which share their data. Depending on what is needed at a given time,
+ * the pixels are converted in place to the Cairo or the GdkPixbuf format.
+ */
+
+/** Create a pixbuf from a Cairo surface.
+ * The constructor takes ownership of the passed surface,
+ * so it should not be destroyed. */
+Pixbuf::Pixbuf(cairo_surface_t *s)
+ : _pixbuf(gdk_pixbuf_new_from_data(
+ cairo_image_surface_get_data(s), GDK_COLORSPACE_RGB, TRUE, 8,
+ cairo_image_surface_get_width(s), cairo_image_surface_get_height(s),
+ cairo_image_surface_get_stride(s), NULL, NULL))
+ , _surface(s)
+ , _mod_time(0)
+ , _pixel_format(PF_CAIRO)
+ , _cairo_store(true)
+{}
+
+/** Create a pixbuf from a GdkPixbuf.
+ * The constructor takes ownership of the passed GdkPixbuf reference,
+ * so it should not be unrefed. */
+Pixbuf::Pixbuf(GdkPixbuf *pb)
+ : _pixbuf(pb)
+ , _surface(0)
+ , _mod_time(0)
+ , _pixel_format(PF_GDK)
+ , _cairo_store(false)
+{
+ _forceAlpha();
+ _surface = cairo_image_surface_create_for_data(
+ gdk_pixbuf_get_pixels(_pixbuf), CAIRO_FORMAT_ARGB32,
+ gdk_pixbuf_get_width(_pixbuf), gdk_pixbuf_get_height(_pixbuf), gdk_pixbuf_get_rowstride(_pixbuf));
+}
+
+Pixbuf::Pixbuf(Inkscape::Pixbuf const &other)
+ : _pixbuf(gdk_pixbuf_copy(other._pixbuf))
+ , _surface(cairo_image_surface_create_for_data(
+ gdk_pixbuf_get_pixels(_pixbuf), CAIRO_FORMAT_ARGB32,
+ gdk_pixbuf_get_width(_pixbuf), gdk_pixbuf_get_height(_pixbuf), gdk_pixbuf_get_rowstride(_pixbuf)))
+ , _mod_time(other._mod_time)
+ , _path(other._path)
+ , _pixel_format(other._pixel_format)
+ , _cairo_store(false)
+{}
+
+Pixbuf::~Pixbuf()
+{
+ if (_cairo_store) {
+ g_object_unref(_pixbuf);
+ cairo_surface_destroy(_surface);
+ } else {
+ cairo_surface_destroy(_surface);
+ g_object_unref(_pixbuf);
+ }
+}
+
+Pixbuf *Pixbuf::create_from_data_uri(gchar const *uri_data)
+{
+ Pixbuf *pixbuf = NULL;
+
+ bool data_is_image = false;
+ bool data_is_base64 = false;
+
+ gchar const *data = uri_data;
+
+ while (*data) {
+ if (strncmp(data,"base64",6) == 0) {
+ /* base64-encoding */
+ data_is_base64 = true;
+ data_is_image = true; // Illustrator produces embedded images without MIME type, so we assume it's image no matter what
+ data += 6;
+ }
+ else if (strncmp(data,"image/png",9) == 0) {
+ /* PNG image */
+ data_is_image = true;
+ data += 9;
+ }
+ else if (strncmp(data,"image/jpg",9) == 0) {
+ /* JPEG image */
+ data_is_image = true;
+ data += 9;
+ }
+ else if (strncmp(data,"image/jpeg",10) == 0) {
+ /* JPEG image */
+ data_is_image = true;
+ data += 10;
+ }
+ else if (strncmp(data,"image/jp2",9) == 0) {
+ /* JPEG2000 image */
+ data_is_image = true;
+ data += 9;
+ }
+ else { /* unrecognized option; skip it */
+ while (*data) {
+ if (((*data) == ';') || ((*data) == ',')) {
+ break;
+ }
+ data++;
+ }
+ }
+ if ((*data) == ';') {
+ data++;
+ continue;
+ }
+ if ((*data) == ',') {
+ data++;
+ break;
+ }
+ }
+
+ if ((*data) && data_is_image && data_is_base64) {
+ GdkPixbuf *buf = NULL;
+ GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
+
+ if (!loader) return NULL;
+
+ gsize decoded_len = 0;
+ guchar *decoded = g_base64_decode(data, &decoded_len);
+
+ if (gdk_pixbuf_loader_write(loader, decoded, decoded_len, NULL)) {
+ gdk_pixbuf_loader_close(loader, NULL);
+ buf = gdk_pixbuf_loader_get_pixbuf(loader);
+ if (buf) {
+ g_object_ref(buf);
+ pixbuf = new Pixbuf(buf);
+
+ GdkPixbufFormat *fmt = gdk_pixbuf_loader_get_format(loader);
+ gchar *fmt_name = gdk_pixbuf_format_get_name(fmt);
+ pixbuf->_setMimeData(decoded, decoded_len, fmt_name);
+ g_free(fmt_name);
+ } else {
+ g_free(decoded);
+ }
+ } else {
+ g_free(decoded);
+ }
+ g_object_unref(loader);
+ }
+
+ return pixbuf;
+}
+
+Pixbuf *Pixbuf::create_from_file(std::string const &fn)
+{
+ Pixbuf *pb = NULL;
+ // test correctness of filename
+ if (!g_file_test(fn.c_str(), G_FILE_TEST_EXISTS)) {
+ return NULL;
+ }
+ struct stat stdir;
+ int val = g_stat(fn.c_str(), &stdir);
+ if (val == 0 && stdir.st_mode & S_IFDIR){
+ return NULL;
+ }
+
+ // we need to load the entire file into memory,
+ // since we'll store it as MIME data
+ gchar *data = NULL;
+ gsize len = 0;
+ GError *error;
+
+ if (g_file_get_contents(fn.c_str(), &data, &len, &error)) {
+
+ GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
+ gdk_pixbuf_loader_write(loader, (guchar *) data, len, NULL);
+ gdk_pixbuf_loader_close(loader, NULL);
+
+ GdkPixbuf *buf = gdk_pixbuf_loader_get_pixbuf(loader);
+ if (buf) {
+ g_object_ref(buf);
+ pb = new Pixbuf(buf);
+ pb->_mod_time = stdir.st_mtime;
+ pb->_path = fn;
+
+ GdkPixbufFormat *fmt = gdk_pixbuf_loader_get_format(loader);
+ gchar *fmt_name = gdk_pixbuf_format_get_name(fmt);
+ pb->_setMimeData((guchar *) data, len, fmt_name);
+ g_free(fmt_name);
+ } else {
+ g_free(data);
+ }
+ g_object_unref(loader);
+
+ // TODO: we could also read DPI, ICC profile, gamma correction, and other information
+ // from the file. This can be done by using format-specific libraries e.g. libpng.
+ } else {
+ return NULL;
+ }
+
+ return pb;
+}
+
+/**
+ * Converts the pixbuf to GdkPixbuf pixel format.
+ * The returned pixbuf can be used e.g. in calls to gdk_pixbuf_save().
+ */
+GdkPixbuf *Pixbuf::getPixbufRaw(bool convert_format)
+{
+ if (convert_format) {
+ ensurePixelFormat(PF_GDK);
+ }
+ return _pixbuf;
+}
+
+/**
+ * Converts the pixbuf to Cairo pixel format and returns an image surface
+ * which can be used as a source.
+ *
+ * The returned surface is owned by the GdkPixbuf and should not be freed.
+ * Calling this function causes the pixbuf to be unsuitable for use
+ * with GTK drawing functions until ensurePixelFormat(Pixbuf::PIXEL_FORMAT_PIXBUF) is called.
+ */
+cairo_surface_t *Pixbuf::getSurfaceRaw(bool convert_format)
+{
+ if (convert_format) {
+ ensurePixelFormat(PF_CAIRO);
+ }
+ return _surface;
+}
+
+/* Declaring this function in the header requires including <gdkmm/pixbuf.h>,
+ * which stupidly includes <glibmm.h> which in turn pulls in <glibmm/threads.h>.
+ * However, since glib 2.32, <glibmm/threads.h> has to be included before <glib.h>
+ * when compiling with G_DISABLE_DEPRECATED, as we do in non-release builds.
+ * This necessitates spamming a lot of files with #include <glibmm/threads.h>
+ * at the top.
+ *
+ * Since we don't really use gdkmm, do not define this function for now. */
+
+/*
+Glib::RefPtr<Gdk::Pixbuf> Pixbuf::getPixbuf(bool convert_format = true)
+{
+ g_object_ref(_pixbuf);
+ Glib::RefPtr<Gdk::Pixbuf> p(getPixbuf(convert_format));
+ return p;
+}
+*/
+
+Cairo::RefPtr<Cairo::Surface> Pixbuf::getSurface(bool convert_format)
+{
+ Cairo::RefPtr<Cairo::Surface> p(new Cairo::Surface(getSurfaceRaw(convert_format), false));
+ return p;
+}
+
+/** Retrieves the original compressed data for the surface, if any.
+ * The returned data belongs to the object and should not be freed. */
+guchar const *Pixbuf::getMimeData(gsize &len, std::string &mimetype) const
+{
+ static gchar const *mimetypes[] = {
+ CAIRO_MIME_TYPE_JPEG, CAIRO_MIME_TYPE_JP2, CAIRO_MIME_TYPE_PNG, NULL };
+ static guint mimetypes_len = g_strv_length(const_cast<gchar**>(mimetypes));
+
+ guchar const *data = NULL;
+
+ for (guint i = 0; i < mimetypes_len; ++i) {
+ unsigned long len_long = 0;
+ cairo_surface_get_mime_data(const_cast<cairo_surface_t*>(_surface), mimetypes[i], &data, &len_long);
+ if (data != NULL) {
+ len = len_long;
+ mimetype = mimetypes[i];
+ break;
+ }
+ }
+
+ return data;
+}
+
+int Pixbuf::width() const {
+ return gdk_pixbuf_get_width(const_cast<GdkPixbuf*>(_pixbuf));
+}
+int Pixbuf::height() const {
+ return gdk_pixbuf_get_height(const_cast<GdkPixbuf*>(_pixbuf));
+}
+int Pixbuf::rowstride() const {
+ return gdk_pixbuf_get_rowstride(const_cast<GdkPixbuf*>(_pixbuf));
+}
+guchar const *Pixbuf::pixels() const {
+ return gdk_pixbuf_get_pixels(const_cast<GdkPixbuf*>(_pixbuf));
+}
+guchar *Pixbuf::pixels() {
+ return gdk_pixbuf_get_pixels(_pixbuf);
+}
+void Pixbuf::markDirty() {
+ cairo_surface_mark_dirty(_surface);
+}
+
+void Pixbuf::_forceAlpha()
+{
+ if (gdk_pixbuf_get_has_alpha(_pixbuf)) return;
+
+ GdkPixbuf *old = _pixbuf;
+ _pixbuf = gdk_pixbuf_add_alpha(old, FALSE, 0, 0, 0);
+ g_object_unref(old);
+}
+
+void Pixbuf::_setMimeData(guchar *data, gsize len, Glib::ustring const &format)
+{
+ gchar const *mimetype = NULL;
+
+ if (format == "jpeg") {
+ mimetype = CAIRO_MIME_TYPE_JPEG;
+ } else if (format == "jpeg2000") {
+ mimetype = CAIRO_MIME_TYPE_JP2;
+ } else if (format == "png") {
+ mimetype = CAIRO_MIME_TYPE_PNG;
+ }
+
+ if (mimetype != NULL) {
+ cairo_surface_set_mime_data(_surface, mimetype, data, len, g_free, data);
+ //g_message("Setting Cairo MIME data: %s", mimetype);
+ } else {
+ g_free(data);
+ //g_message("Not setting Cairo MIME data: unknown format %s", name.c_str());
+ }
+}
+
+void Pixbuf::ensurePixelFormat(PixelFormat fmt)
+{
+ if (_pixel_format == PF_GDK) {
+ if (fmt == PF_GDK) {
+ return;
+ }
+ if (fmt == PF_CAIRO) {
+ convert_pixels_pixbuf_to_argb32(
+ gdk_pixbuf_get_pixels(_pixbuf),
+ gdk_pixbuf_get_width(_pixbuf),
+ gdk_pixbuf_get_height(_pixbuf),
+ gdk_pixbuf_get_rowstride(_pixbuf));
+ _pixel_format = fmt;
+ return;
+ }
+ g_assert_not_reached();
+ }
+ if (_pixel_format == PF_CAIRO) {
+ if (fmt == PF_GDK) {
+ convert_pixels_argb32_to_pixbuf(
+ gdk_pixbuf_get_pixels(_pixbuf),
+ gdk_pixbuf_get_width(_pixbuf),
+ gdk_pixbuf_get_height(_pixbuf),
+ gdk_pixbuf_get_rowstride(_pixbuf));
+ _pixel_format = fmt;
+ return;
+ }
+ if (fmt == PF_CAIRO) {
+ return;
+ }
+ g_assert_not_reached();
+ }
+ g_assert_not_reached();
+}
+
} // namespace Inkscape
/*
@@ -371,129 +749,6 @@ ink_cairo_pattern_set_matrix(cairo_pattern_t *cp, Geom::Affine const &m)
cairo_pattern_set_matrix(cp, &cm);
}
-void
-ink_cairo_set_source_pixbuf(cairo_t *ct, GdkPixbuf *pb, double x, double y)
-{
- cairo_surface_t *pbs = ink_cairo_surface_get_for_pixbuf(pb);
- cairo_set_source_surface(ct, pbs, x, y);
-}
-
-/* The functions below implement the following hack:
- *
- * The pixels formats of Cairo and GdkPixbuf are different.
- * GdkPixbuf accesses pixels as bytes, alpha is not premultiplied,
- * and successive bytes of a single pixel contain R, G, B and A components.
- * Cairo accesses pixels as 32-bit ints, alpha is premultiplied,
- * and each int contains as 0xAARRGGBB, accessed with bitwise operations.
- *
- * In other words, on a little endian system, a GdkPixbuf will contain:
- * char *data = "rgbargbargba...."
- * int *data = { 0xAABBGGRR, 0xAABBGGRR, 0xAABBGGRR, ... }
- * while a Cairo image surface will contain:
- * char *data = "bgrabgrabgra...."
- * int *data = { 0xAARRGGBB, 0xAARRGGBB, 0xAARRGGBB, ... }
- *
- * It is possible to convert between these two formats (almost) losslessly.
- * Some color information from partially transparent regions of the image
- * is lost, but the result when displaying this image will remain the same.
- *
- * The functions below allow interoperation between GdkPixbuf
- * and Cairo surfaces, allowing pixbufs to be used as Cairo sources,
- * and saving Cairo surfaces using GdkPixbuf APIs.
- * This is implemented by creating a GdkPixbuf and a Cairo image surface
- * which share their data. Depending on what is needed at a given time,
- * the pixels are converted in place to the Cairo or the GdkPixbuf format.
- * In this way, only one copy of the image data is needed.
- *
- * Given either a GdkPixbuf or a Cairo surface, these functions create
- * the other object and convert to its format. The returned object should be
- * freed using cairo_surface_destroy or g_object_unref when it's no longer
- * needed.
- *
- * Memory ownership semantics:
- * Regardless of whether the pixels are stored in memory originally belonging
- * to Cairo surface or to GdkPixbuf, the GdkPixbuf is the master object.
- * To free the memory, unref the GdkPixbuf ONLY.
- */
-
-/**
- * Converts the pixbuf to Cairo pixel format and returns an image surface
- * which can be used as a source.
- *
- * The returned surface is owned by the GdkPixbuf and should not be freed.
- * Calling this function causes the pixbuf to be unsuitable for use
- * with GTK drawing functions until ink_pixbuf_ensure_normal() is called.
- *
- * @bug You have to call g_object_set_data(G_OBJECT(pb), "cairo_surface", NULL)
- * when unrefing the last reference to the pixbuf. Otherwise there will be
- * crashes, because cairo_surface_destroy is called after the pixbuf data
- * is already freed.
- */
-cairo_surface_t *
-ink_cairo_surface_get_for_pixbuf(GdkPixbuf *pb)
-{
- cairo_surface_t *pbs =
- reinterpret_cast<cairo_surface_t*>(g_object_get_data(G_OBJECT(pb), "cairo_surface"));
-
- ink_pixbuf_ensure_argb32(pb);
-
- if (pbs == NULL) {
- guchar *data = gdk_pixbuf_get_pixels(pb);
- int w = gdk_pixbuf_get_width(pb);
- int h = gdk_pixbuf_get_height(pb);
- int stride = gdk_pixbuf_get_rowstride(pb);
-
- // create a surface that stores the data
- pbs = cairo_image_surface_create_for_data(
- data, CAIRO_FORMAT_ARGB32, w, h, stride);
-
- g_object_set_data_full(G_OBJECT(pb), "cairo_surface", pbs, (GDestroyNotify) cairo_surface_destroy);
- cairo_surface_set_user_data(pbs, &ink_pixbuf_key, pb, NULL);
- }
-
- return pbs;
-}
-
-/**
- * Converts the Cairo surface to GdkPixbuf pixel format.
- * GdkPixbuf takes ownership of the passed surface reference,
- * so it should NOT be freed after calling this function.
- */
-GdkPixbuf *ink_pixbuf_create_from_cairo_surface(cairo_surface_t *s)
-{
- GdkPixbuf *pb = reinterpret_cast<GdkPixbuf*>(cairo_surface_get_user_data(s, &ink_pixbuf_key));
- if (pb == NULL) {
- pb = gdk_pixbuf_new_from_data(
- cairo_image_surface_get_data(s), GDK_COLORSPACE_RGB, TRUE, 8,
- cairo_image_surface_get_width(s), cairo_image_surface_get_height(s),
- cairo_image_surface_get_stride(s), NULL, NULL);
-
- g_object_set_data_full(G_OBJECT(pb), "pixel_format", g_strdup("argb32"), g_free);
- g_object_set_data_full(G_OBJECT(pb), "cairo_surface", s, (GDestroyNotify) cairo_surface_destroy);
-
- cairo_surface_set_user_data(s, &ink_pixbuf_key, pb, NULL);
- } else {
- g_warning("Received surface which is already owned by GdkPixbuf");
- g_object_ref(pb);
- }
-
- ink_pixbuf_ensure_normal(pb);
-
- return pb;
-}
-
-/**
- * Cleanup function for GdkPixbuf.
- * This function should be passed as the GdkPixbufDestroyNotify parameter
- * to gdk_pixbuf_new_from_data when creating a GdkPixbuf backed by
- * a Cairo surface.
- */
-void ink_cairo_pixbuf_cleanup(guchar * /*pixels*/, void *data)
-{
- cairo_surface_t *surface = reinterpret_cast<cairo_surface_t*>(data);
- cairo_surface_destroy(surface);
-}
-
/**
* Create an exact copy of a surface.
* Creates a surface that has the same type, content type, dimensions and contents
@@ -833,6 +1088,44 @@ ink_cairo_pattern_create_checkerboard()
return p;
}
+/**
+ * Converts the Cairo surface to a GdkPixbuf pixel format,
+ * without allocating extra memory.
+ *
+ * This function is intended mainly for creating previews displayed by GTK.
+ * For loading images for display on the canvas, use the Inkscape::Pixbuf object.
+ *
+ * The returned GdkPixbuf takes ownership of the passed surface reference,
+ * so it should NOT be freed after calling this function.
+ */
+GdkPixbuf *ink_pixbuf_create_from_cairo_surface(cairo_surface_t *s)
+{
+ guchar *pixels = cairo_image_surface_get_data(s);
+ int w = cairo_image_surface_get_width(s);
+ int h = cairo_image_surface_get_height(s);
+ int rs = cairo_image_surface_get_stride(s);
+
+ convert_pixels_argb32_to_pixbuf(pixels, w, h, rs);
+
+ GdkPixbuf *pb = gdk_pixbuf_new_from_data(
+ pixels, GDK_COLORSPACE_RGB, TRUE, 8,
+ w, h, rs, ink_cairo_pixbuf_cleanup, s);
+
+ return pb;
+}
+
+/**
+ * Cleanup function for GdkPixbuf.
+ * This function should be passed as the GdkPixbufDestroyNotify parameter
+ * to gdk_pixbuf_new_from_data when creating a GdkPixbuf backed by
+ * a Cairo surface.
+ */
+static void ink_cairo_pixbuf_cleanup(guchar * /*pixels*/, void *data)
+{
+ cairo_surface_t *surface = static_cast<cairo_surface_t*>(data);
+ cairo_surface_destroy(surface);
+}
+
/* The following two functions use "from" instead of "to", because when you write:
val1 = argb32_from_pixbuf(val1);
the name of the format is closer to the value in that format. */
diff --git a/src/display/cairo-utils.h b/src/display/cairo-utils.h
index 289d4e01f..505e2ca77 100644
--- a/src/display/cairo-utils.h
+++ b/src/display/cairo-utils.h
@@ -12,14 +12,15 @@
#ifndef SEEN_INKSCAPE_DISPLAY_CAIRO_UTILS_H
#define SEEN_INKSCAPE_DISPLAY_CAIRO_UTILS_H
+#include <boost/noncopyable.hpp>
+//#include <glibmm/threads.h> // workaround
#include <glib.h>
#include <cairomm/cairomm.h>
+//#include <gdkmm/pixbuf.h>
#include <2geom/forward.h>
#include "style.h"
struct SPColor;
-struct _GdkPixbuf;
-typedef struct _GdkPixbuf GdkPixbuf;
namespace Inkscape {
@@ -80,15 +81,61 @@ public:
static Cairo::RefPtr<CairoContext> create(Cairo::RefPtr<Cairo::Surface> const &target);
};
-} // namespace Inkscape
+/** Class to hold image data for raster images.
+ * Allows easy interoperation with GdkPixbuf and Cairo. */
+class Pixbuf {
+public:
+ enum PixelFormat {
+ PF_CAIRO = 1,
+ PF_GDK = 2,
+ PF_LAST
+ };
+
+ explicit Pixbuf(cairo_surface_t *s);
+ explicit Pixbuf(GdkPixbuf *pb);
+ Pixbuf(Inkscape::Pixbuf const &other);
+ ~Pixbuf();
+
+ GdkPixbuf *getPixbufRaw(bool convert_format = true);
+ //Glib::RefPtr<Gdk::Pixbuf> getPixbuf(bool convert_format = true);
+
+ cairo_surface_t *getSurfaceRaw(bool convert_format = true);
+ Cairo::RefPtr<Cairo::Surface> getSurface(bool convert_format = true);
+
+ int width() const;
+ int height() const;
+ int rowstride() const;
+ guchar const *pixels() const;
+ guchar *pixels();
+ void markDirty();
+
+ bool hasMimeData() const;
+ guchar const *getMimeData(gsize &len, std::string &mimetype) const;
+ std::string const &originalPath() const { return _path; }
+ time_t modificationTime() const { return _mod_time; }
-enum InkPixelFormat {
- INK_PIXEL_FORMAT_NONE,
- INK_PIXEL_FORMAT_CAIRO,
- INK_PIXEL_FORMAT_PIXBUF,
- INK_PIXEL_FORMAT_LAST
+ PixelFormat pixelFormat() const { return _pixel_format; }
+ void ensurePixelFormat(PixelFormat fmt);
+
+ static Pixbuf *create_from_data_uri(gchar const *uri);
+ static Pixbuf *create_from_file(std::string const &fn);
+
+private:
+ void _ensurePixelsARGB32();
+ void _ensurePixelsPixbuf();
+ void _forceAlpha();
+ void _setMimeData(guchar *data, gsize len, Glib::ustring const &format);
+
+ GdkPixbuf *_pixbuf;
+ cairo_surface_t *_surface;
+ time_t _mod_time;
+ std::string _path;
+ PixelFormat _pixel_format;
+ bool _cairo_store;
};
+} // namespace Inkscape
+
// TODO: these declarations may not be needed in the header
extern cairo_user_data_key_t ink_color_interpolation_key;
extern cairo_user_data_key_t ink_pixbuf_key;
@@ -102,7 +149,6 @@ void ink_cairo_set_source_color(cairo_t *ct, SPColor const &color, double opacit
void ink_cairo_set_source_rgba32(cairo_t *ct, guint32 rgba);
void ink_cairo_transform(cairo_t *ct, Geom::Affine const &m);
void ink_cairo_pattern_set_matrix(cairo_pattern_t *cp, Geom::Affine const &m);
-void ink_cairo_set_source_pixbuf(cairo_t *ct, GdkPixbuf *pb, double x, double y);
void ink_matrix_to_2geom(Geom::Affine &, cairo_matrix_t const &);
void ink_matrix_to_cairo(cairo_matrix_t &, Geom::Affine const &);
@@ -125,13 +171,9 @@ int ink_cairo_surface_linear_to_srgb(cairo_surface_t *surface);
cairo_pattern_t *ink_cairo_pattern_create_checkerboard();
+GdkPixbuf *ink_pixbuf_create_from_cairo_surface(cairo_surface_t *s);
void convert_pixels_pixbuf_to_argb32(guchar *data, int w, int h, int rs);
void convert_pixels_argb32_to_pixbuf(guchar *data, int w, int h, int rs);
-void ink_pixbuf_ensure_argb32(GdkPixbuf *);
-void ink_pixbuf_ensure_normal(GdkPixbuf *);
-cairo_surface_t *ink_cairo_surface_get_for_pixbuf(GdkPixbuf *pb);
-GdkPixbuf *ink_pixbuf_create_from_cairo_surface(cairo_surface_t *s);
-void ink_cairo_pixbuf_cleanup(guchar *pixels, void *surface);
G_GNUC_CONST guint32 argb32_from_pixbuf(guint32 in);
G_GNUC_CONST guint32 pixbuf_from_argb32(guint32 in);
diff --git a/src/display/drawing-image.cpp b/src/display/drawing-image.cpp
index 46f066b8e..0b661a450 100644
--- a/src/display/drawing-image.cpp
+++ b/src/display/drawing-image.cpp
@@ -22,34 +22,23 @@ namespace Inkscape {
DrawingImage::DrawingImage(Drawing &drawing)
: DrawingItem(drawing)
, _pixbuf(NULL)
- , _surface(NULL) // this is owned by _pixbuf!
, _style(NULL)
, _new_surface(NULL)
{}
DrawingImage::~DrawingImage()
{
- if (_style)
+ if (_style) {
sp_style_unref(_style);
- if (_pixbuf) {
- if (_new_surface) cairo_surface_destroy(_new_surface);
- g_object_unref(_pixbuf);
}
+
+ // _pixbuf is owned by SPImage - do not delete it
}
void
-DrawingImage::setARGB32Pixbuf(GdkPixbuf *pb)
+DrawingImage::setPixbuf(Inkscape::Pixbuf *pb)
{
- // when done in this order, it won't break if pb == image->pixbuf and the refcount is 1
- if (pb != NULL) {
- g_object_ref (pb);
- }
- if (_pixbuf != NULL) {
- g_object_unref(_pixbuf);
- // unrefing the pixbuf also destroys surface
- }
_pixbuf = pb;
- _surface = pb ? ink_cairo_surface_get_for_pixbuf(pb) : NULL;
_markForUpdate(STATE_ALL, false);
}
@@ -86,8 +75,8 @@ DrawingImage::bounds() const
{
if (!_pixbuf) return _clipbox;
- double pw = gdk_pixbuf_get_width(_pixbuf);
- double ph = gdk_pixbuf_get_height(_pixbuf);
+ double pw = _pixbuf->width();
+ double ph = _pixbuf->height();
double vw = pw * _scale[Geom::X];
double vh = ph * _scale[Geom::Y];
Geom::Point wh(vw, vh);
@@ -143,14 +132,16 @@ unsigned DrawingImage::_renderItem(DrawingContext &ct, Geom::IntRect const &/*ar
// See https://bugs.launchpad.net/inkscape/+bug/804162
Geom::Scale expansion(_ctm.expansion());
- int orgwidth = cairo_image_surface_get_width(_surface);
- int orgheight = cairo_image_surface_get_height(_surface);
+ int orgwidth = _pixbuf->width();
+ int orgheight = _pixbuf->height();
if (_scale[Geom::X]*expansion[Geom::X]*orgwidth*255.0<1.0 || _scale[Geom::Y]*expansion[Geom::Y]*orgheight*255.0<1.0) {
// Resized image too small to actually see anything
return RENDER_OK;
}
-
+
+ _pixbuf->ensurePixelFormat(Inkscape::Pixbuf::PF_CAIRO);
+
// Split scale*expansion in a part that is <= 1.0 and a part that is >= 1.0. We only take care of the part <= 1.0.
Geom::Scale scaleExpansionSmall(std::min<Geom::Coord>(fabs(_scale[Geom::X]*expansion[Geom::X]),1),std::min<Geom::Coord>(fabs(_scale[Geom::Y]*expansion[Geom::Y]),1));
Geom::Scale scaleExpansionLarge(_scale[Geom::X]*expansion[Geom::X]/scaleExpansionSmall[Geom::X],_scale[Geom::Y]*expansion[Geom::Y]/scaleExpansionSmall[Geom::Y]);
@@ -161,7 +152,7 @@ unsigned DrawingImage::_renderItem(DrawingContext &ct, Geom::IntRect const &/*ar
ct.scale(expansion.inverse()); // This should not include scale (see derivation above)
ct.translate(_origin*expansion);
ct.scale(scaleExpansionLarge);
- ct.setSource(_surface, 0, 0);
+ ct.setSource(_pixbuf->getSurfaceRaw(), 0, 0);
} else if (!_new_surface || (newSize-_rescaledSize).length()>0.1) {
// Rescaled image is sufficiently different from cached image to recompute
if (_new_surface) cairo_surface_destroy(_new_surface);
@@ -200,13 +191,13 @@ unsigned DrawingImage::_renderItem(DrawingContext &ct, Geom::IntRect const &/*ar
}
}
+ cairo_surface_t *surface = _pixbuf->getSurfaceRaw();
_new_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, newwidth,newheight);
- unsigned char * orgdata = cairo_image_surface_get_data(_surface);
+ unsigned char * orgdata = cairo_image_surface_get_data(surface);
unsigned char * newdata = cairo_image_surface_get_data(_new_surface);
- int orgstride = cairo_image_surface_get_stride(_surface);
+ int orgstride = cairo_image_surface_get_stride(surface);
int newstride = cairo_image_surface_get_stride(_new_surface);
-
- //cairo_surface_flush(_surface);
+
cairo_surface_flush(_new_surface);
for(int y=0; y<newheight; y++) {
@@ -245,7 +236,7 @@ unsigned DrawingImage::_renderItem(DrawingContext &ct, Geom::IntRect const &/*ar
// TODO: If Cairo's problems are gone, uncomment the following:
//ct.translate(_origin);
//ct.scale(_scale);
- //ct.setSource(_surface, 0, 0);
+ //ct.setSource(_pixbuf->getSurfaceRaw(), 0, 0);
//ct.paint(_opacity);
ct.paint();
@@ -315,10 +306,10 @@ DrawingImage::_pickItem(Geom::Point const &p, double delta, unsigned /*sticky*/)
return NULL;
} else {
- unsigned char *const pixels = gdk_pixbuf_get_pixels(_pixbuf);
- int width = gdk_pixbuf_get_width(_pixbuf);
- int height = gdk_pixbuf_get_height(_pixbuf);
- int rowstride = gdk_pixbuf_get_rowstride(_pixbuf);
+ unsigned char *const pixels = _pixbuf->pixels();
+ int width = _pixbuf->width();
+ int height = _pixbuf->height();
+ int rowstride = _pixbuf->rowstride();
Geom::Point tp = p * _ctm.inverse();
Geom::Rect r = bounds();
@@ -336,8 +327,17 @@ DrawingImage::_pickItem(Geom::Point const &p, double delta, unsigned /*sticky*/)
unsigned char *pix_ptr = pixels + iy * rowstride + ix * 4;
// pick if the image is less than 99% transparent
- float alpha = (pix_ptr[3] / 255.0f) * _opacity;
- return alpha > 0.01 ? this : NULL;
+ guint32 alpha = 0;
+ if (_pixbuf->pixelFormat() == Inkscape::Pixbuf::PF_CAIRO) {
+ guint32 px = *reinterpret_cast<guint32 const *>(pix_ptr);
+ alpha = (px & 0xff000000) >> 24;
+ } else if (_pixbuf->pixelFormat() == Inkscape::Pixbuf::PF_GDK) {
+ alpha = pix_ptr[3];
+ } else {
+ throw std::runtime_error("Unrecognized pixel format");
+ }
+ float alpha_f = (alpha / 255.0f) * _opacity;
+ return alpha_f > 0.01 ? this : NULL;
}
}
diff --git a/src/display/drawing-image.h b/src/display/drawing-image.h
index 593185c97..58e6de72e 100644
--- a/src/display/drawing-image.h
+++ b/src/display/drawing-image.h
@@ -19,6 +19,7 @@
#include "display/drawing-item.h"
namespace Inkscape {
+class Pixbuf;
class DrawingImage
: public DrawingItem
@@ -27,7 +28,7 @@ public:
DrawingImage(Drawing &drawing);
~DrawingImage();
- void setARGB32Pixbuf(GdkPixbuf *pb);
+ void setPixbuf(Inkscape::Pixbuf *pb);
void setStyle(SPStyle *style);
void setScale(double sx, double sy);
void setOrigin(Geom::Point const &o);
@@ -41,8 +42,7 @@ protected:
DrawingItem *stop_at);
virtual DrawingItem *_pickItem(Geom::Point const &p, double delta, unsigned flags);
- GdkPixbuf *_pixbuf;
- cairo_surface_t *_surface;
+ Inkscape::Pixbuf *_pixbuf;
SPStyle *_style;
cairo_surface_t *_new_surface; // Part of hack around Cairo bug
diff --git a/src/display/drawing-item.cpp b/src/display/drawing-item.cpp
index 80664d822..a9836a9e3 100644
--- a/src/display/drawing-item.cpp
+++ b/src/display/drawing-item.cpp
@@ -284,7 +284,7 @@ DrawingItem::setZOrder(unsigned z)
void
DrawingItem::setItemBounds(Geom::OptRect const &bounds)
{
- _item_bbox = bounds;
+ if (bounds) _filter_bbox = bounds;
}
/**
@@ -352,8 +352,10 @@ DrawingItem::update(Geom::IntRect const &area, UpdateContext const &ctx, unsigne
if (to_update & STATE_BBOX) {
// compute drawbox
- if (_filter && render_filters) {
- _drawbox = _filter->compute_drawbox(this, _item_bbox);
+ if (_filter && render_filters && _bbox) {
+ Geom::IntRect newbox(*_bbox);
+ _filter->area_enlarge(newbox, this);
+ _drawbox = Geom::OptIntRect(newbox);
} else {
_drawbox = _bbox;
}
diff --git a/src/display/drawing-item.h b/src/display/drawing-item.h
index 4a516512b..8020659db 100644
--- a/src/display/drawing-item.h
+++ b/src/display/drawing-item.h
@@ -89,7 +89,7 @@ public:
Geom::OptIntRect geometricBounds() const { return _bbox; }
Geom::OptIntRect visualBounds() const { return _drawbox; }
- Geom::OptRect itemBounds() const { return _item_bbox; }
+ Geom::OptRect filterBounds() const { return _filter_bbox; }
Geom::Affine ctm() const { return _ctm; }
Geom::Affine transform() const { return _transform ? *_transform : Geom::identity(); }
Drawing &drawing() const { return _drawing; }
@@ -175,7 +175,7 @@ protected:
Geom::Affine _ctm; ///< Total transform from item coords to display coords
Geom::OptIntRect _bbox; ///< Bounding box in display (pixel) coords including stroke
Geom::OptIntRect _drawbox; ///< Full visual bounding box - enlarged by filters, shrunk by clips and masks
- Geom::OptRect _item_bbox; ///< Geometric bounding box in item coordinates
+ Geom::OptRect _filter_bbox; ///< Used by filters when settings bounds
DrawingItem *_clip;
DrawingItem *_mask;
diff --git a/src/display/drawing-shape.cpp b/src/display/drawing-shape.cpp
index e80f12486..e689d0755 100644
--- a/src/display/drawing-shape.cpp
+++ b/src/display/drawing-shape.cpp
@@ -179,8 +179,8 @@ DrawingShape::_renderItem(DrawingContext &ct, Geom::IntRect const &area, unsigne
// update fill and stroke paints.
// this cannot be done during nr_arena_shape_update, because we need a Cairo context
// to render svg:pattern
- has_fill = _nrstyle.prepareFill(ct, _item_bbox);
- has_stroke = _nrstyle.prepareStroke(ct, _item_bbox);
+ has_fill = _nrstyle.prepareFill(ct, _bbox);
+ has_stroke = _nrstyle.prepareStroke(ct, _bbox);
has_stroke &= (_nrstyle.stroke_width != 0);
if (has_fill || has_stroke) {
diff --git a/src/display/drawing-text.cpp b/src/display/drawing-text.cpp
index 234006983..fa9ce4ff8 100644
--- a/src/display/drawing-text.cpp
+++ b/src/display/drawing-text.cpp
@@ -398,8 +398,8 @@ unsigned DrawingText::_renderItem(DrawingContext &ct, Geom::IntRect const &/*are
using Geom::X;
using Geom::Y;
- has_fill = _nrstyle.prepareFill( ct, _item_bbox);
- has_stroke = _nrstyle.prepareStroke(ct, _item_bbox);
+ has_fill = _nrstyle.prepareFill( ct, _bbox);
+ has_stroke = _nrstyle.prepareStroke(ct, _bbox);
if (has_fill || has_stroke) {
Geom::Affine rotinv;
@@ -441,7 +441,7 @@ unsigned DrawingText::_renderItem(DrawingContext &ct, Geom::IntRect const &/*are
}
Inkscape::DrawingContext::Save save(ct);
-// ct.transform(_ctm); // Seems to work fine without this line, which was in the original.
+ ct.transform(_ctm); // For one thing, this is needed to scale a fill-pattern when zooming in
if (has_fill) {
_nrstyle.applyFill(ct);
ct.fillPreserve();
diff --git a/src/display/nr-filter-image.cpp b/src/display/nr-filter-image.cpp
index b9d73f0ad..4ca4cd07c 100644
--- a/src/display/nr-filter-image.cpp
+++ b/src/display/nr-filter-image.cpp
@@ -30,6 +30,7 @@ FilterImage::FilterImage()
: SVGElem(0)
, document(0)
, feImageHref(0)
+ , image(0)
, broken_ref(false)
{ }
@@ -41,7 +42,7 @@ FilterImage::~FilterImage()
{
if (feImageHref)
g_free(feImageHref);
- g_object_set_data(G_OBJECT(image->gobj()), "cairo_surface", NULL);
+ delete image;
}
void FilterImage::render_cairo(FilterSlot &slot)
@@ -131,50 +132,38 @@ void FilterImage::render_cairo(FilterSlot &slot)
// External image, like <image>
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->base is valid,
- * 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->getBase(), 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 );
- return;
+
+ /* 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->base is valid,
+ * 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->getBase(), feImageHref, NULL );
}
- 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: %s", e.what().data() );
+ if ( !g_file_test( fullname, G_FILE_TEST_EXISTS ) ) {
+ // Should display Broken Image png.
+ g_warning("FilterImage::render: Can not find: %s", feImageHref );
return;
}
- catch (const Gdk::PixbufError & e)
- {
- g_warning("Gdk::PixbufError in FilterImage::render: %s", e.what().data() );
+ image = Inkscape::Pixbuf::create_from_file(fullname);
+ if( fullname != feImageHref ) g_free( fullname );
+
+ if ( !image ) {
+ g_warning("FilterImage::render: failed to load image: %s", feImageHref);
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);
- }
}
- cairo_surface_t *image_surface = ink_cairo_surface_get_for_pixbuf(image->gobj());
+ cairo_surface_t *image_surface = image->getSurfaceRaw();
Geom::Rect sa = slot.get_slot_area();
cairo_surface_t *out = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
@@ -199,7 +188,7 @@ void FilterImage::render_cairo(FilterSlot &slot)
// Check aspect ratio of image vs. viewport
double feAspect = feImageHeight/feImageWidth;
- double aspect = (double)image->get_height()/(double)image->get_width();
+ double aspect = (double)image->height()/(double)image->width();
bool ratio = (feAspect < aspect);
double ax, ay; // Align side
@@ -274,8 +263,8 @@ void FilterImage::render_cairo(FilterSlot &slot)
}
}
- double scaleX = feImageWidth / image->get_width();
- double scaleY = feImageHeight / image->get_height();
+ double scaleX = feImageWidth / image->width();
+ double scaleY = feImageHeight / image->height();
cairo_translate(ct, feImageX, feImageY);
cairo_scale(ct, scaleX, scaleY);
@@ -302,8 +291,8 @@ void FilterImage::set_href(const gchar *href){
if (feImageHref) g_free (feImageHref);
feImageHref = (href) ? g_strdup (href) : NULL;
- g_object_set_data(G_OBJECT(image->gobj()), "cairo_surface", NULL);
- image.reset();
+ delete image;
+ image = NULL;
broken_ref = false;
}
diff --git a/src/display/nr-filter-image.h b/src/display/nr-filter-image.h
index f45f42265..69691ac99 100644
--- a/src/display/nr-filter-image.h
+++ b/src/display/nr-filter-image.h
@@ -12,14 +12,14 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <gdkmm/pixbuf.h>
#include "display/nr-filter-primitive.h"
-#include <glibmm/refptr.h>
class SPDocument;
class SPItem;
namespace Inkscape {
+class Pixbuf;
+
namespace Filters {
class FilterSlot;
@@ -43,7 +43,7 @@ public:
private:
SPDocument *document;
gchar *feImageHref;
- Glib::RefPtr<Gdk::Pixbuf> image;
+ Inkscape::Pixbuf *image;
float feImageX, feImageY, feImageWidth, feImageHeight;
unsigned int aspect_align, aspect_clip;
bool broken_ref;
diff --git a/src/display/nr-filter.cpp b/src/display/nr-filter.cpp
index f0965c460..a0103cbb0 100644
--- a/src/display/nr-filter.cpp
+++ b/src/display/nr-filter.cpp
@@ -114,13 +114,16 @@ int Filter::render(Inkscape::DrawingItem const *item, DrawingContext &graphic, D
Geom::Affine trans = item->ctm();
-// Geom::OptRect filter_area = filter_effect_area(item->itemBounds()); // disabled, already done in visualBounds
- Geom::OptRect filter_area = item->itemBounds(); // see LP Bug 1188336
- if (!filter_area) return 1;
+ // Get filter are, the filter_effect_area is already done in visualBounds
+ Geom::OptRect filter_area = item->filterBounds();
+ // Use the geometricBounds as a backup solution
+ if (!filter_area || (filter_area->hasZeroArea() &&
+ filter_area->min()[Geom::X] == 0 && filter_area->min()[Geom::Y] == 0))
+ filter_area = item->geometricBounds();
FilterUnits units(_filter_units, _primitive_units);
units.set_ctm(trans);
- units.set_item_bbox(item->itemBounds());
+ units.set_item_bbox(filter_area);
units.set_filter_area(*filter_area);
std::pair<double,double> resolution
@@ -200,7 +203,7 @@ void Filter::area_enlarge(Geom::IntRect &bbox, Inkscape::DrawingItem const *item
}
Geom::Rect item_bbox;
- Geom::OptRect maybe_bbox = item->itemBounds();
+ Geom::OptRect maybe_bbox = item->geometricBounds();
if (maybe_bbox.isEmpty()) {
// Code below needs a bounding box
return;
@@ -220,20 +223,6 @@ void Filter::area_enlarge(Geom::IntRect &bbox, Inkscape::DrawingItem const *item
*/
}
-Geom::OptIntRect Filter::compute_drawbox(Inkscape::DrawingItem const *item, Geom::OptRect const &item_bbox) {
-
-// Geom::OptRect enlarged = filter_effect_area(item_bbox); // disabled, already done in visualBounds
- Geom::OptRect enlarged = item_bbox; // see LP Bug 1188336
- if (enlarged) {
- *enlarged *= item->ctm();
-
- Geom::OptIntRect ret(enlarged->roundOutwards());
- return ret;
- } else {
- return Geom::OptIntRect();
- }
-}
-
Geom::OptRect Filter::filter_effect_area(Geom::OptRect const &bbox)
{
Geom::Point minp, maxp;
diff --git a/src/display/nr-filter.h b/src/display/nr-filter.h
index d53005c5d..5df38ffe9 100644
--- a/src/display/nr-filter.h
+++ b/src/display/nr-filter.h
@@ -151,12 +151,6 @@ public:
*/
void area_enlarge(Geom::IntRect &area, Inkscape::DrawingItem const *item) const;
/**
- * Given an item bounding box (in user coords), this function enlarges it
- * to contain the filter effects region and transforms it to screen
- * coordinates
- */
- Geom::OptIntRect compute_drawbox(Inkscape::DrawingItem const *item, Geom::OptRect const &item_bbox);
- /**
* Returns the filter effects area in user coordinate system.
* The given bounding box should be a bounding box as specified in
* SVG standard and in user coordinate system.