Code

feMorphology filter primitive implementation
[inkscape.git] / src / sp-image.cpp
index 961661fc6bf0bba063e1ffc6dea41f4b85b6587f..d535874e93c34d8ba69d0b91bb6fa1774704474e 100644 (file)
@@ -21,6 +21,7 @@
 //#define GDK_PIXBUF_ENABLE_BACKEND 1
 //#include <gdk-pixbuf/gdk-pixbuf-io.h>
 #include "display/nr-arena-image.h"
+#include <display/curve.h>
 
 //Added for preserveAspectRatio support -- EAF
 #include "enums.h"
 #include "brokenimage.xpm"
 #include "document.h"
 #include "sp-image.h"
+#include "sp-clippath.h"
 #include <glibmm/i18n.h>
 #include "xml/quote.h"
 #include <xml/repr.h>
 
+#include "libnr/nr-matrix-fns.h"
+
 #include "io/sys.h"
 #include <png.h>
 #if ENABLE_LCMS
@@ -65,6 +69,8 @@ static gchar * sp_image_description (SPItem * item);
 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);
+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_pixbuf_force_rgba (GdkPixbuf * pixbuf);
@@ -502,6 +508,7 @@ sp_image_init (SPImage *image)
        image->width.unset();
        image->height.unset();
        image->aspect_align = SP_ASPECT_NONE;
+       image->curve = NULL;
 }
 
 static void
@@ -551,6 +558,10 @@ sp_image_release (SPObject *object)
        }
 #endif // ENABLE_LCMS
 
+    if (image->curve) {
+               image->curve = sp_curve_unref (image->curve);
+       }
+
        if (((SPObjectClass *) parent_class)->release)
                ((SPObjectClass *) parent_class)->release (object);
 }
@@ -676,6 +687,8 @@ sp_image_set (SPObject *object, unsigned int key, const gchar *value)
                        ((SPObjectClass *) (parent_class))->set (object, key, value);
                break;
        }
+       
+       sp_image_set_curve(image); //creates a curve at the image's boundary for snapping
 }
 
 static void
@@ -697,8 +710,8 @@ sp_image_update (SPObject *object, SPCtx *ctx, unsigned int flags)
                if (image->href) {
                        GdkPixbuf *pixbuf;
                        pixbuf = sp_image_repr_read_image (
-                    object->repr->attribute("xlink:href"), 
-                    object->repr->attribute("sodipodi:absref"), 
+                    object->repr->attribute("xlink:href"),
+                    object->repr->attribute("sodipodi:absref"),
                     doc->base);
                        if (pixbuf) {
                                pixbuf = sp_image_pixbuf_force_rgba (pixbuf);
@@ -740,7 +753,7 @@ sp_image_update (SPObject *object, SPCtx *ctx, unsigned int flags)
                                                         intent = INTENT_PERCEPTUAL;
                                                 }
                                                 cmsHPROFILE destProf = cmsCreate_sRGBProfile();
-                                                cmsHTRANSFORM transf = cmsCreateTransform( prof, 
+                                                cmsHTRANSFORM transf = cmsCreateTransform( prof,
                                                                                            TYPE_RGBA_8,
                                                                                            destProf,
                                                                                            TYPE_RGBA_8,
@@ -873,7 +886,6 @@ sp_image_update (SPObject *object, SPCtx *ctx, unsigned int flags)
                                }
                        }
        }
-
        sp_image_update_canvas_image ((SPImage *) object);
 }
 
@@ -1062,7 +1074,7 @@ sp_image_repr_read_image (const gchar *href, const gchar *absref, const gchar *b
                 if (!docbase) docbase = ".";
                 fullname = g_build_filename(docbase, filename, NULL);
 
-                // document base can be wrong (on the temporary doc when importing bitmap from a 
+                // 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)) {
@@ -1070,7 +1082,7 @@ sp_image_repr_read_image (const gchar *href, const gchar *absref, const gchar *b
                     g_free (fullname);
                     if (pixbuf != NULL) return pixbuf;
                 }
-            } 
+            }
 
             /* try filename as absolute */
             if (g_file_test (filename, G_FILE_TEST_EXISTS) && !g_file_test (filename, G_FILE_TEST_IS_DIR)) {
@@ -1084,7 +1096,11 @@ sp_image_repr_read_image (const gchar *href, const gchar *absref, const gchar *b
     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);
+        if ( base != NULL && href != NULL )
+               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);
+               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 );
         if (pixbuf != NULL) return pixbuf;
     }
@@ -1160,9 +1176,30 @@ sp_image_update_canvas_image (SPImage *image)
 
 static void sp_image_snappoints(SPItem const *item, SnapPointsIter p)
 {
-     if (((SPItemClass *) parent_class)->snappoints) {
-         ((SPItemClass *) parent_class)->snappoints (item, p);
-     }
+    /* An image doesn't have any nodes to snap, but still we want to be able snap one image 
+    to another. Therefore we will create some snappoints at the corner, similar to a rect. If
+    the image is rotated, then the snappoints will rotate with it. Again, just like a rect.
+    */
+     
+    g_assert(item != NULL);
+    g_assert(SP_IS_IMAGE(item));
+
+    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
+    } else {
+        // The image has not been clipped: return its corners, which might be rotated for example
+        SPImage &image = *SP_IMAGE(item);
+        double const x0 = image.x.computed;
+               double const y0 = image.y.computed;
+               double const x1 = x0 + image.width.computed;
+               double const y1 = y0 + image.height.computed;
+               NR::Matrix const i2d (sp_item_i2d_affine (item));
+               *p = NR::Point(x0, y0) * i2d;
+        *p = NR::Point(x0, y1) * i2d;
+        *p = NR::Point(x1, y1) * i2d;
+        *p = NR::Point(x1, y0) * i2d;
+    }
 }
 
 /*
@@ -1351,6 +1388,45 @@ sp_image_repr_read_b64 (const gchar * uri_data)
        return pixbuf;
 }
 
+static void
+sp_image_set_curve(SPImage *image) 
+{
+    //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);
+        }
+        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);
+        
+    if (image->curve) {
+        image->curve = sp_curve_unref(image->curve);
+    }
+    
+    if (c) {
+        image->curve = sp_curve_ref(c);
+    }
+    
+    sp_curve_unref(c);    
+}
+
+/**
+ * Return duplicate of curve (if any exists) or NULL if there is no curve
+ */
+SPCurve *
+sp_image_get_curve (SPImage *image)
+{
+       if (image->curve) {
+               return sp_curve_copy(image->curve);
+       }
+       return NULL;
+}
+
 /*
   Local Variables:
   mode:c++