diff --git a/src/sp-image.cpp b/src/sp-image.cpp
index 6cc3830a7bd1e3555fddd26e34ee156273828612..5a02517e260267d27800ca44e2de314c7fbde740 100644 (file)
--- a/src/sp-image.cpp
+++ b/src/sp-image.cpp
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
-#include <libnr/nr-matrix-fns.h>
+#include <cstring>
+#include <string>
+#include <libnr/nr-matrix-fns.h>
+#include <libnr/nr-matrix-ops.h>
+#include <libnr/nr-translate-matrix-ops.h>
+#include <libnr/nr-scale-translate-ops.h>
+#include <libnr/nr-convert2geom.h>
+#include <2geom/rect.h>
//#define GDK_PIXBUF_ENABLE_BACKEND 1
//#include <gdk-pixbuf/gdk-pixbuf-io.h>
#include "display/nr-arena-image.h"
#include <display/curve.h>
+#include <glib/gstdio.h>
//Added for preserveAspectRatio support -- EAF
#include "enums.h"
static void sp_image_release (SPObject * object);
static void sp_image_set (SPObject *object, unsigned int key, const gchar *value);
static void sp_image_update (SPObject *object, SPCtx *ctx, unsigned int flags);
-static Inkscape::XML::Node *sp_image_write (SPObject *object, Inkscape::XML::Node *repr, guint flags);
+static Inkscape::XML::Node *sp_image_write (SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags);
static void sp_image_bbox(SPItem const *item, NRRect *bbox, NR::Matrix const &transform, unsigned const flags);
static void sp_image_print (SPItem * item, SPPrintContext *ctx);
static void sp_image_set_curve(SPImage *image);
-GdkPixbuf *sp_image_repr_read_image (const gchar *href, const gchar *absref, const gchar *base);
+static GdkPixbuf *sp_image_repr_read_image( time_t& modTime, gchar*& pixPath, const gchar *href, const gchar *absref, const gchar *base );
static GdkPixbuf *sp_image_pixbuf_force_rgba (GdkPixbuf * pixbuf);
static void sp_image_update_canvas_image (SPImage *image);
static GdkPixbuf * sp_image_repr_read_dataURI (const gchar * uri_data);
// g_message("things out");
}
-void user_write_data( png_structp png_ptr, png_bytep data, png_size_t length )
+void user_write_data( png_structp /*png_ptr*/, png_bytep /*data*/, png_size_t /*length*/ )
{
//g_message( "user_write_data(%d)", length );
}
-void user_flush_data( png_structp png_ptr )
+void user_flush_data( png_structp /*png_ptr*/ )
{
//g_message( "user_flush_data" );
}
-GdkPixbuf* pixbuf_new_from_file( const char *filename, GError **error )
+static GdkPixbuf* pixbuf_new_from_file( const char *filename, time_t &modTime, gchar*& pixPath, GError **/*error*/ )
{
GdkPixbuf* buf = NULL;
PushPull youme;
gint dpiX = 0;
gint dpiY = 0;
+ modTime = 0;
+ if ( pixPath ) {
+ g_free(pixPath);
+ pixPath = 0;
+ }
//buf = gdk_pixbuf_new_from_file( filename, error );
dump_fopen_call( filename, "pixbuf_new_from_file" );
FILE* fp = fopen_utf8name( filename, "r" );
if ( fp )
{
+ {
+ struct stat st;
+ memset(&st, 0, sizeof(st));
+ int val = g_stat(filename, &st);
+ if ( !val ) {
+ modTime = st.st_mtime;
+ pixPath = g_strdup(filename);
+ }
+ }
+
GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
if ( loader )
{
return buf;
}
+GdkPixbuf* pixbuf_new_from_file( const char *filename, GError **error )
+{
+ time_t modTime = 0;
+ gchar* pixPath = 0;
+ GdkPixbuf* result = pixbuf_new_from_file( filename, modTime, pixPath, error );
+ if (pixPath) {
+ g_free(pixPath);
+ }
+ return result;
+}
+
+
}
}
GType
sp_image_get_type (void)
{
- static GType image_type = 0;
- if (!image_type) {
- GTypeInfo image_info = {
- sizeof (SPImageClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) sp_image_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (SPImage),
- 16, /* n_preallocs */
- (GInstanceInitFunc) sp_image_init,
- NULL, /* value_table */
- };
- image_type = g_type_register_static (sp_item_get_type (), "SPImage", &image_info, (GTypeFlags)0);
- }
- return image_type;
+ static GType image_type = 0;
+ if (!image_type) {
+ GTypeInfo image_info = {
+ sizeof (SPImageClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) sp_image_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (SPImage),
+ 16, /* n_preallocs */
+ (GInstanceInitFunc) sp_image_init,
+ NULL, /* value_table */
+ };
+ image_type = g_type_register_static (sp_item_get_type (), "SPImage", &image_info, (GTypeFlags)0);
+ }
+ return image_type;
}
static void
sp_image_class_init (SPImageClass * klass)
{
- GObjectClass * gobject_class;
- SPObjectClass * sp_object_class;
- SPItemClass * item_class;
-
- gobject_class = (GObjectClass *) klass;
- sp_object_class = (SPObjectClass *) klass;
- item_class = (SPItemClass *) klass;
-
- parent_class = (SPItemClass*)g_type_class_ref (sp_item_get_type ());
-
- sp_object_class->build = sp_image_build;
- sp_object_class->release = sp_image_release;
- sp_object_class->set = sp_image_set;
- sp_object_class->update = sp_image_update;
- sp_object_class->write = sp_image_write;
-
- item_class->bbox = sp_image_bbox;
- item_class->print = sp_image_print;
- item_class->description = sp_image_description;
- item_class->show = sp_image_show;
- item_class->snappoints = sp_image_snappoints;
- item_class->set_transform = sp_image_set_transform;
+ GObjectClass * gobject_class;
+ SPObjectClass * sp_object_class;
+ SPItemClass * item_class;
+
+ gobject_class = (GObjectClass *) klass;
+ sp_object_class = (SPObjectClass *) klass;
+ item_class = (SPItemClass *) klass;
+
+ parent_class = (SPItemClass*)g_type_class_ref (sp_item_get_type ());
+
+ sp_object_class->build = sp_image_build;
+ sp_object_class->release = sp_image_release;
+ sp_object_class->set = sp_image_set;
+ sp_object_class->update = sp_image_update;
+ sp_object_class->write = sp_image_write;
+
+ item_class->bbox = sp_image_bbox;
+ item_class->print = sp_image_print;
+ item_class->description = sp_image_description;
+ item_class->show = sp_image_show;
+ item_class->snappoints = sp_image_snappoints;
+ item_class->set_transform = sp_image_set_transform;
}
-static void
-sp_image_init (SPImage *image)
+static void sp_image_init( SPImage *image )
{
- image->x.unset();
- image->y.unset();
- image->width.unset();
- image->height.unset();
- image->aspect_align = SP_ASPECT_NONE;
- image->curve = NULL;
+ image->x.unset();
+ image->y.unset();
+ image->width.unset();
+ image->height.unset();
+ image->aspect_align = SP_ASPECT_NONE;
+
+ image->trimx = 0;
+ image->trimy = 0;
+ image->trimwidth = 0;
+ image->trimheight = 0;
+ image->viewx = 0;
+ image->viewy = 0;
+ image->viewwidth = 0;
+ image->viewheight = 0;
+
+ image->curve = NULL;
+
+ image->href = 0;
+#if ENABLE_LCMS
+ image->color_profile = 0;
+#endif // ENABLE_LCMS
+ image->pixbuf = 0;
+ image->pixPath = 0;
+ image->lastMod = 0;
}
static void
@@ -586,38 +638,42 @@ sp_image_build (SPObject *object, SPDocument *document, Inkscape::XML::Node *rep
static void
sp_image_release (SPObject *object)
{
- SPImage *image;
+ SPImage *image = SP_IMAGE(object);
- image = SP_IMAGE (object);
-
- if (SP_OBJECT_DOCUMENT (object)) {
- /* Unregister ourselves */
- sp_document_remove_resource (SP_OBJECT_DOCUMENT (object), "image", SP_OBJECT (object));
- }
+ if (SP_OBJECT_DOCUMENT (object)) {
+ /* Unregister ourselves */
+ sp_document_remove_resource (SP_OBJECT_DOCUMENT (object), "image", SP_OBJECT (object));
+ }
- if (image->href) {
- g_free (image->href);
- image->href = NULL;
- }
+ if (image->href) {
+ g_free (image->href);
+ image->href = NULL;
+ }
- if (image->pixbuf) {
- gdk_pixbuf_unref (image->pixbuf);
- image->pixbuf = NULL;
- }
+ if (image->pixbuf) {
+ gdk_pixbuf_unref (image->pixbuf);
+ image->pixbuf = NULL;
+ }
#if ENABLE_LCMS
- if (image->color_profile) {
- g_free (image->color_profile);
- image->color_profile = NULL;
- }
+ if (image->color_profile) {
+ g_free (image->color_profile);
+ image->color_profile = NULL;
+ }
#endif // ENABLE_LCMS
+ if (image->pixPath) {
+ g_free(image->pixPath);
+ image->pixPath = 0;
+ }
+
if (image->curve) {
- image->curve = sp_curve_unref (image->curve);
- }
+ image->curve = image->curve->unref();
+ }
- if (((SPObjectClass *) parent_class)->release)
- ((SPObjectClass *) parent_class)->release (object);
+ if (((SPObjectClass *) parent_class)->release) {
+ ((SPObjectClass *) parent_class)->release (object);
+ }
}
static void
static void
sp_image_update (SPObject *object, SPCtx *ctx, unsigned int flags)
{
- SPImage *image;
-
- image = (SPImage *) object;
+ SPImage *image = SP_IMAGE(object);
SPDocument *doc = SP_OBJECT_DOCUMENT(object);
- if (((SPObjectClass *) (parent_class))->update)
- ((SPObjectClass *) (parent_class))->update (object, ctx, flags);
+ if (((SPObjectClass *) (parent_class))->update)
+ ((SPObjectClass *) (parent_class))->update (object, ctx, flags);
- if (flags & SP_IMAGE_HREF_MODIFIED_FLAG) {
- if (image->pixbuf) {
- gdk_pixbuf_unref (image->pixbuf);
- image->pixbuf = NULL;
- }
- if (image->href) {
- GdkPixbuf *pixbuf;
- pixbuf = sp_image_repr_read_image (
- object->repr->attribute("xlink:href"),
- object->repr->attribute("sodipodi:absref"),
- doc->base);
- if (pixbuf) {
- pixbuf = sp_image_pixbuf_force_rgba (pixbuf);
+ if (flags & SP_IMAGE_HREF_MODIFIED_FLAG) {
+ if (image->pixbuf) {
+ gdk_pixbuf_unref (image->pixbuf);
+ image->pixbuf = NULL;
+ }
+ if ( image->pixPath ) {
+ g_free(image->pixPath);
+ image->pixPath = 0;
+ }
+ image->lastMod = 0;
+ if (image->href) {
+ GdkPixbuf *pixbuf;
+ pixbuf = sp_image_repr_read_image (
+ image->lastMod,
+ image->pixPath,
+ object->repr->attribute("xlink:href"),
+ object->repr->attribute("sodipodi:absref"),
+ doc->base);
+ if (pixbuf) {
+ pixbuf = sp_image_pixbuf_force_rgba (pixbuf);
// BLIP
#if ENABLE_LCMS
if ( image->color_profile )
}
static Inkscape::XML::Node *
-sp_image_write (SPObject *object, Inkscape::XML::Node *repr, guint flags)
+sp_image_write (SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags)
{
SPImage *image;
image = SP_IMAGE (object);
if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
- Inkscape::XML::Document *xml_doc = sp_document_repr_doc(SP_OBJECT_DOCUMENT(object));
repr = xml_doc->createElement("svg:image");
}
#endif // ENABLE_LCMS
if (((SPObjectClass *) (parent_class))->write)
- ((SPObjectClass *) (parent_class))->write (object, repr, flags);
+ ((SPObjectClass *) (parent_class))->write (object, xml_doc, repr, flags);
return repr;
}
static void
-sp_image_bbox(SPItem const *item, NRRect *bbox, NR::Matrix const &transform, unsigned const flags)
+sp_image_bbox(SPItem const *item, NRRect *bbox, NR::Matrix const &transform, unsigned const /*flags*/)
{
SPImage const &image = *SP_IMAGE(item);
sp_image_print (SPItem *item, SPPrintContext *ctx)
{
SPImage *image;
- NRMatrix tp, ti, s, t;
guchar *px;
int w, h, rs, pixskip;
rs = gdk_pixbuf_get_rowstride (image->pixbuf);
pixskip = gdk_pixbuf_get_n_channels (image->pixbuf) * gdk_pixbuf_get_bits_per_sample (image->pixbuf) / 8;
+ NR::Matrix t;
if (image->aspect_align == SP_ASPECT_NONE) {
/* fixme: (Lauris) */
- nr_matrix_set_translate (&tp, image->x.computed, image->y.computed);
- nr_matrix_set_scale (&s, image->width.computed, -image->height.computed);
- nr_matrix_set_translate (&ti, 0.0, -1.0);
+ NR::translate tp = NR::translate(image->x.computed, image->y.computed);
+ NR::scale s = NR::scale(image->width.computed, -image->height.computed);
+ NR::translate ti = NR::translate(0.0, -1.0);
+ t = s * tp;
+ t = ti * t;
} else { // preserveAspectRatio
- nr_matrix_set_translate (&tp, image->viewx, image->viewy);
- nr_matrix_set_scale (&s, image->viewwidth, -image->viewheight);
- nr_matrix_set_translate (&ti, 0.0, -1.0);
+ NR::translate tp = NR::translate(image->viewx, image->viewy);
+ NR::scale s = NR::scale(image->viewwidth, -image->viewheight);
+ NR::translate ti = NR::translate(0.0, -1.0);
+ t = s * tp;
+ t = ti * t;
}
- nr_matrix_multiply (&t, &s, &tp);
- nr_matrix_multiply (&t, &ti, &t);
-
if (image->aspect_align == SP_ASPECT_NONE)
sp_print_image_R8G8B8A8_N (ctx, px, w, h, rs, &t, SP_OBJECT_STYLE (item));
else // preserveAspectRatio
}
static NRArenaItem *
-sp_image_show (SPItem *item, NRArena *arena, unsigned int key, unsigned int flags)
+sp_image_show (SPItem *item, NRArena *arena, unsigned int /*key*/, unsigned int /*flags*/)
{
int pixskip, rs;
SPImage * image;
@@ -1099,12 +1160,16 @@ sp_image_show (SPItem *item, NRArena *arena, unsigned int key, unsigned int flag
*
*/
-GdkPixbuf *
-sp_image_repr_read_image (const gchar *href, const gchar *absref, const gchar *base)
+GdkPixbuf *sp_image_repr_read_image( time_t& modTime, char*& pixPath, const gchar *href, const gchar *absref, const gchar *base )
{
const gchar *filename, *docbase;
gchar *fullname;
GdkPixbuf *pixbuf;
+ modTime = 0;
+ if ( pixPath ) {
+ g_free(pixPath);
+ pixPath = 0;
+ }
filename = href;
if (filename != NULL) {
@@ -1112,7 +1177,7 @@ sp_image_repr_read_image (const gchar *href, const gchar *absref, const gchar *b
fullname = g_filename_from_uri(filename, NULL, NULL);
if (fullname) {
// TODO check this. Was doing a UTF-8 to filename conversion here.
- pixbuf = Inkscape::IO::pixbuf_new_from_file (fullname, NULL);
+ pixbuf = Inkscape::IO::pixbuf_new_from_file (fullname, modTime, pixPath, NULL);
if (pixbuf != NULL) return pixbuf;
}
} else if (strncmp (filename,"data:",5) == 0) {
@@ -1132,7 +1197,7 @@ sp_image_repr_read_image (const gchar *href, const gchar *absref, const gchar *b
// different dir) or unset (when doc is not saved yet), so we check for base+href existence first,
// and if it fails, we also try to use bare href regardless of its g_path_is_absolute
if (g_file_test (fullname, G_FILE_TEST_EXISTS) && !g_file_test (fullname, G_FILE_TEST_IS_DIR)) {
- pixbuf = Inkscape::IO::pixbuf_new_from_file( fullname, NULL );
+ pixbuf = Inkscape::IO::pixbuf_new_from_file( fullname, modTime, pixPath, NULL );
g_free (fullname);
if (pixbuf != NULL) return pixbuf;
}
@@ -1140,7 +1205,7 @@ sp_image_repr_read_image (const gchar *href, const gchar *absref, const gchar *b
/* try filename as absolute */
if (g_file_test (filename, G_FILE_TEST_EXISTS) && !g_file_test (filename, G_FILE_TEST_IS_DIR)) {
- pixbuf = Inkscape::IO::pixbuf_new_from_file( filename, NULL );
+ pixbuf = Inkscape::IO::pixbuf_new_from_file( filename, modTime, pixPath, NULL );
if (pixbuf != NULL) return pixbuf;
}
}
@@ -1155,7 +1220,7 @@ sp_image_repr_read_image (const gchar *href, const gchar *absref, const gchar *b
else
g_warning ("xlink:href did not resolve to a valid image file, now trying sodipodi:absref=\"%s\"", absref);
- pixbuf = Inkscape::IO::pixbuf_new_from_file( filename, NULL );
+ pixbuf = Inkscape::IO::pixbuf_new_from_file( filename, modTime, pixPath, NULL );
if (pixbuf != NULL) return pixbuf;
}
/* Nope: We do not find any valid pixmap file :-( */
if (item->clip_ref->getObject()) {
//We are looking at a clipped image: do not return any snappoints, as these might be
//far far away from the visible part from the clipped image
+ //TODO Do return snappoints, but only when within visual bounding box
} else {
// The image has not been clipped: return its corners, which might be rotated for example
SPImage &image = *SP_IMAGE(item);
//create a curve at the image's boundary for snapping
if ((image->height.computed < 1e-18) || (image->width.computed < 1e-18) || (image->clip_ref->getObject())) {
if (image->curve) {
- image->curve = sp_curve_unref(image->curve);
+ image->curve = image->curve->unref();
}
return;
}
NRRect rect;
sp_image_bbox(image, &rect, NR::identity(), 0);
- NR::Maybe<NR::Rect> rect2 = rect.upgrade();
- SPCurve *c = sp_curve_new_from_rect(rect2);
+ Geom::Rect rect2 = to_2geom(*rect.upgrade());
+ SPCurve *c = SPCurve::new_from_rect(rect2);
if (image->curve) {
- image->curve = sp_curve_unref(image->curve);
+ image->curve = image->curve->unref();
}
if (c) {
- image->curve = sp_curve_ref(c);
+ image->curve = c->ref();
}
- sp_curve_unref(c);
+ c->unref();
}
/**
sp_image_get_curve (SPImage *image)
{
if (image->curve) {
- return sp_curve_copy(image->curve);
+ return image->curve->copy();
}
return NULL;
}
+void sp_image_refresh_if_outdated( SPImage* image )
+{
+ if ( image->href && image->lastMod ) {
+ // It *might* change
+
+ struct stat st;
+ memset(&st, 0, sizeof(st));
+ int val = g_stat(image->pixPath, &st);
+ if ( !val ) {
+ // stat call worked. Check time now
+ if ( st.st_mtime != image->lastMod ) {
+ SPCtx *ctx = 0;
+ unsigned int flags = SP_IMAGE_HREF_MODIFIED_FLAG;
+ sp_image_update(image, ctx, flags);
+ }
+ }
+ }
+}
+
/*
Local Variables:
mode:c++