Code

fix leftover rubberband after switching to selector while dragging
[inkscape.git] / src / sp-image.cpp
index 83b623dbc80f4f7b1248f10bdeec569236cf9abc..961661fc6bf0bba063e1ffc6dea41f4b85b6587f 100644 (file)
 #if ENABLE_LCMS
 #include "color-profile-fns.h"
 #include "color-profile.h"
+//#define DEBUG_LCMS
+#ifdef DEBUG_LCMS
+#include "prefs-utils.h"
+#include <gtk/gtkmessagedialog.h>
+#endif // DEBUG_LCMS
 #endif // ENABLE_LCMS
 /*
  * SPImage
@@ -61,7 +66,7 @@ static void sp_image_snappoints(SPItem const *item, SnapPointsIter p);
 static NRArenaItem *sp_image_show (SPItem *item, NRArena *arena, unsigned int key, unsigned int flags);
 static NR::Matrix sp_image_set_transform (SPItem *item, NR::Matrix const &xform);
 
-GdkPixbuf * sp_image_repr_read_image (Inkscape::XML::Node * repr);
+GdkPixbuf *sp_image_repr_read_image (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);
@@ -78,6 +83,36 @@ extern "C"
 
 }
 
+
+#ifdef DEBUG_LCMS
+extern guint update_in_progress;
+#define DEBUG_MESSAGE(key, ...) \
+{\
+    gint dump = prefs_get_int_attribute_limited("options.scislac", #key, 0, 0, 1);\
+    gint dumpD = prefs_get_int_attribute_limited("options.scislac", #key"D", 0, 0, 1);\
+    gint dumpD2 = prefs_get_int_attribute_limited("options.scislac", #key"D2", 0, 0, 1);\
+    dumpD &= ( (update_in_progress == 0) || dumpD2 );\
+    if ( dump )\
+    {\
+        g_message( __VA_ARGS__ );\
+\
+    }\
+    if ( dumpD )\
+    {\
+        GtkWidget *dialog = gtk_message_dialog_new(NULL,\
+                                                   GTK_DIALOG_DESTROY_WITH_PARENT, \
+                                                   GTK_MESSAGE_INFO,    \
+                                                   GTK_BUTTONS_OK,      \
+                                                   __VA_ARGS__          \
+                                                   );\
+        g_signal_connect_swapped(dialog, "response",\
+                                 G_CALLBACK(gtk_widget_destroy),        \
+                                 dialog);                               \
+        gtk_widget_show_all( dialog );\
+    }\
+}
+#endif // DEBUG_LCMS
+
 namespace Inkscape {
 namespace IO {
 
@@ -625,6 +660,13 @@ sp_image_set (SPObject *object, unsigned int key, const gchar *value)
                     g_free (image->color_profile);
                 }
                 image->color_profile = (value) ? g_strdup (value) : NULL;
+#ifdef DEBUG_LCMS
+                if ( value ) {
+                    DEBUG_MESSAGE( lcmsFour, "<image> color-profile set to '%s'", value );
+                } else {
+                    DEBUG_MESSAGE( lcmsFour, "<image> color-profile cleared" );
+                }
+#endif // DEBUG_LCMS
                 // TODO check on this HREF_MODIFIED flag
                 object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_IMAGE_HREF_MODIFIED_FLAG);
                 break;
@@ -639,9 +681,10 @@ sp_image_set (SPObject *object, unsigned int key, const gchar *value)
 static void
 sp_image_update (SPObject *object, SPCtx *ctx, unsigned int flags)
 {
-       SPImage *image;
+    SPImage *image;
 
-       image = (SPImage *) object;
+    image = (SPImage *) object;
+    SPDocument *doc = SP_OBJECT_DOCUMENT(object);
 
        if (((SPObjectClass *) (parent_class))->update)
                ((SPObjectClass *) (parent_class))->update (object, ctx, flags);
@@ -653,7 +696,10 @@ sp_image_update (SPObject *object, SPCtx *ctx, unsigned int flags)
                }
                if (image->href) {
                        GdkPixbuf *pixbuf;
-                       pixbuf = sp_image_repr_read_image (object->repr);
+                       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);
 // BLIP
@@ -666,6 +712,9 @@ sp_image_update (SPObject *object, SPCtx *ctx, unsigned int flags)
                                     guchar* px = gdk_pixbuf_get_pixels( pixbuf );
 
                                     if ( px ) {
+#ifdef DEBUG_LCMS
+                                        DEBUG_MESSAGE( lcmsFive, "in <image>'s sp_image_update. About to call colorprofile_get_handle()" );
+#endif // DEBUG_LCMS
                                         guint profIntent = Inkscape::RENDERING_INTENT_UNKNOWN;
                                         cmsHPROFILE prof = Inkscape::colorprofile_get_handle( SP_OBJECT_DOCUMENT( object ),
                                                                                               &profIntent,
@@ -706,9 +755,27 @@ sp_image_update (SPObject *object, SPCtx *ctx, unsigned int flags)
 
                                                     cmsDeleteTransform( transf );
                                                 }
+#ifdef DEBUG_LCMS
+                                                else
+                                                {
+                                                    DEBUG_MESSAGE( lcmsSix, "in <image>'s sp_image_update. Unable to create LCMS transform." );
+                                                }
+#endif // DEBUG_LCMS
                                                 cmsCloseProfile( destProf );
                                             }
+#ifdef DEBUG_LCMS
+                                            else
+                                            {
+                                                DEBUG_MESSAGE( lcmsSeven, "in <image>'s sp_image_update. Profile type is named color. Can't transform." );
+                                            }
+#endif // DEBUG_LCMS
+                                        }
+#ifdef DEBUG_LCMS
+                                        else
+                                        {
+                                            DEBUG_MESSAGE( lcmsEight, "in <image>'s sp_image_update. No profile found." );
                                         }
+#endif // DEBUG_LCMS
                                     }
                                 }
 #endif // ENABLE_LCMS
@@ -818,7 +885,8 @@ sp_image_write (SPObject *object, Inkscape::XML::Node *repr, guint flags)
        image = SP_IMAGE (object);
 
        if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
-               repr = sp_repr_new ("svg:image");
+                Inkscape::XML::Document *xml_doc = sp_document_repr_doc(SP_OBJECT_DOCUMENT(object));
+               repr = xml_doc->createElement("svg:image");
        }
 
        repr->setAttribute("xlink:href", image->href);
@@ -906,7 +974,7 @@ sp_image_description(SPItem *item)
                 : xml_quote_strdup(image->href);
         } else {
             g_warning("Attempting to call strncmp() with a null pointer.");
-            href_desc = g_strdup(_("(null_pointer)")); // we call g_free() on href_desc
+            href_desc = g_strdup("(null_pointer)"); // we call g_free() on href_desc
         }
 
        char *ret = ( image->pixbuf == NULL
@@ -933,6 +1001,7 @@ sp_image_show (SPItem *item, NRArena *arena, unsigned int key, unsigned int flag
        if (image->pixbuf) {
                pixskip = gdk_pixbuf_get_n_channels (image->pixbuf) * gdk_pixbuf_get_bits_per_sample (image->pixbuf) / 8;
                rs = gdk_pixbuf_get_rowstride (image->pixbuf);
+                nr_arena_image_set_style(NR_ARENA_IMAGE(ai), SP_OBJECT_STYLE(SP_OBJECT(item)));
                if (image->aspect_align == SP_ASPECT_NONE)
                        nr_arena_image_set_pixels (NR_ARENA_IMAGE (ai),
                                           gdk_pixbuf_get_pixels (image->pixbuf),
@@ -965,55 +1034,68 @@ sp_image_show (SPItem *item, NRArena *arena, unsigned int key, unsigned int flag
  */
 
 GdkPixbuf *
-sp_image_repr_read_image (Inkscape::XML::Node * repr)
+sp_image_repr_read_image (const gchar *href, const gchar *absref, const gchar *base)
 {
-       const gchar * filename, * docbase;
-       gchar * fullname;
-       GdkPixbuf * pixbuf;
-
-       filename = repr->attribute("xlink:href");
-       if (filename == NULL) filename = repr->attribute("href"); /* FIXME */
-       if (filename != NULL) {
-               if (strncmp (filename,"file:",5) == 0) {
-                       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);
-                               if (pixbuf != NULL) return pixbuf;
-                       }
-               } else if (strncmp (filename,"data:",5) == 0) {
-                       /* data URI - embedded image */
-                       filename += 5;
-                       pixbuf = sp_image_repr_read_dataURI (filename);
-                       if (pixbuf != NULL) return pixbuf;
-               } else if (!g_path_is_absolute (filename)) {
-                       /* try to load from relative pos */
-                       docbase = sp_repr_document_root (sp_repr_document (repr))->attribute("sodipodi:docbase");
-                       if (!docbase) docbase = ".";
-                       fullname = g_build_filename(docbase, filename, NULL);
-                       pixbuf = Inkscape::IO::pixbuf_new_from_file( fullname, NULL );
-                       g_free (fullname);
-                       if (pixbuf != NULL) return pixbuf;
-               } else {
-                       /* try absolute filename */
-                       pixbuf = Inkscape::IO::pixbuf_new_from_file( filename, NULL );
-                       if (pixbuf != NULL) return pixbuf;
-               }
-       }
-       /* at last try to load from sp absolute path name */
-       filename = repr->attribute("sodipodi:absref");
-       if (filename != NULL) {
-               pixbuf = Inkscape::IO::pixbuf_new_from_file( filename, NULL );
-               if (pixbuf != NULL) return pixbuf;
-       }
-       /* Nope: We do not find any valid pixmap file :-( */
-       pixbuf = gdk_pixbuf_new_from_xpm_data ((const gchar **) brokenimage_xpm);
+    const gchar *filename, *docbase;
+    gchar *fullname;
+    GdkPixbuf *pixbuf;
+
+    filename = href;
+    if (filename != NULL) {
+        if (strncmp (filename,"file:",5) == 0) {
+            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);
+                if (pixbuf != NULL) return pixbuf;
+            }
+        } else if (strncmp (filename,"data:",5) == 0) {
+            /* data URI - embedded image */
+            filename += 5;
+            pixbuf = sp_image_repr_read_dataURI (filename);
+            if (pixbuf != NULL) return pixbuf;
+        } else {
 
-       /* It should be included xpm, so if it still does not does load, */
-       /* our libraries are broken */
-       g_assert (pixbuf != NULL);
+            if (!g_path_is_absolute (filename)) {
+                /* try to load from relative pos combined with document base*/
+                docbase = base;
+                if (!docbase) docbase = ".";
+                fullname = g_build_filename(docbase, filename, NULL);
+
+                // document base can be wrong (on the temporary doc when importing bitmap from a 
+                // 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 );
+                    g_free (fullname);
+                    if (pixbuf != NULL) return pixbuf;
+                }
+            } 
 
-       return pixbuf;
+            /* 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 );
+                if (pixbuf != NULL) return pixbuf;
+            }
+        }
+    }
+
+    /* at last try to load from sp absolute path name */
+    filename = absref;
+    if (filename != NULL) {
+        // using absref is outside of SVG rules, so we must at least warn the user
+        g_warning ("<image xlink:href=\"%s\"> did not resolve to a valid image file (base dir is %s), now trying sodipodi:absref=\"%s\"", href, base, absref);
+        pixbuf = Inkscape::IO::pixbuf_new_from_file( filename, NULL );
+        if (pixbuf != NULL) return pixbuf;
+    }
+    /* Nope: We do not find any valid pixmap file :-( */
+    pixbuf = gdk_pixbuf_new_from_xpm_data ((const gchar **) brokenimage_xpm);
+
+    /* It should be included xpm, so if it still does not does load, */
+    /* our libraries are broken */
+    g_assert (pixbuf != NULL);
+
+    return pixbuf;
 }
 
 static GdkPixbuf *
@@ -1053,6 +1135,7 @@ sp_image_update_canvas_image (SPImage *image)
        for (v = item->display; v != NULL; v = v->next) {
                pixskip = gdk_pixbuf_get_n_channels (image->pixbuf) * gdk_pixbuf_get_bits_per_sample (image->pixbuf) / 8;
                rs = gdk_pixbuf_get_rowstride (image->pixbuf);
+                nr_arena_image_set_style (NR_ARENA_IMAGE(v->arenaitem), SP_OBJECT_STYLE(SP_OBJECT(image)));
                if (image->aspect_align == SP_ASPECT_NONE) {
                        nr_arena_image_set_pixels (NR_ARENA_IMAGE (v->arenaitem),
                                           gdk_pixbuf_get_pixels (image->pixbuf),