Code

implementing snapping to images
authordvlierop2 <dvlierop2@users.sourceforge.net>
Tue, 26 Jun 2007 21:07:31 +0000 (21:07 +0000)
committerdvlierop2 <dvlierop2@users.sourceforge.net>
Tue, 26 Jun 2007 21:07:31 +0000 (21:07 +0000)
src/object-snapper.cpp
src/sp-image.cpp
src/sp-image.h
src/sp-item.cpp
src/splivarot.cpp

index 8d5b30dffea2c58482a25fc4517d7be63af1eb9a..a904bd93baa52505d016819338abeb3fb531cd31 100644 (file)
@@ -15,7 +15,9 @@
 #include "document.h"
 #include "sp-namedview.h"
 #include "sp-path.h"
+#include "sp-image.h"
 #include "sp-item-group.h"
+#include "sp-item.h"
 #include "sp-use.h"
 #include "display/curve.h"
 #include "desktop.h"
@@ -89,27 +91,33 @@ void Inkscape::ObjectSnapper::_snapNodes(Inkscape::SnappedPoint &s,
             root_item = *i;
         }
         
+        SPCurve *curve = NULL;
+        
         if (SP_IS_SHAPE(root_item)) {
-
             SPShape const *sh = SP_SHAPE(root_item);
-            if (sh->curve) {
-
-                int j = 0;
-
-                while (SP_CURVE_BPATH(sh->curve)[j].code != NR_END) {
-            
-                    /* Get this node in desktop coordinates */
-                    NArtBpath const &bp = SP_CURVE_BPATH(sh->curve)[j];
-                    NR::Point const n = desktop->doc2dt(bp.c(3) * i2doc);
+            curve = sh->curve;
+        } else if (SP_IS_IMAGE(root_item)) {
+            SPImage const *im = SP_IMAGE(root_item);
+            curve = im->curve;
+        }
             
-                    /* Try to snap to this node of the path */
-                    NR::Coord const dist = NR::L2(n - p);
-                    if (dist < getDistance() && dist < s.getDistance()) {
-                        s = SnappedPoint(n, dist);
-                    }
+        if (curve) {
 
-                    j++;
+            int j = 0;
+
+            while (SP_CURVE_BPATH(curve)[j].code != NR_END) {
+        
+                /* Get this node in desktop coordinates */
+                NArtBpath const &bp = SP_CURVE_BPATH(curve)[j];
+                NR::Point const n = desktop->doc2dt(bp.c(3) * i2doc);
+        
+                /* Try to snap to this node of the path */
+                NR::Coord const dist = NR::L2(n - p);
+                if (dist < getDistance() && dist < s.getDistance()) {
+                    s = SnappedPoint(n, dist);
                 }
+
+                j++;
             }
         }
     }
@@ -126,13 +134,13 @@ void Inkscape::ObjectSnapper::_snapPaths(Inkscape::SnappedPoint &s,
     SPDesktop const *desktop = SP_ACTIVE_DESKTOP;
 
     NR::Point const p_doc = desktop->dt2doc(p);
-
+    
     for (std::list<SPItem*>::const_iterator i = cand.begin(); i != cand.end(); i++) {
 
         /* Transform the requested snap point to this item's coordinates */
         NR::Matrix i2doc(NR::identity());
         SPItem *root_item = NULL;
-        /* We might have a clone at hand, so make sure we get the root item */        
+        /* We might have a clone at hand, so make sure we get the root item */
         if (SP_IS_USE(*i)) {
             i2doc = sp_use_get_root_transform(SP_USE(*i));
             root_item = sp_use_root(SP_USE(*i));
index d710c109e907263856646c76be221dd0cb52f36a..6ff6bb806339d14fd983638b617c565e0a63faa1 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"
@@ -30,6 +31,7 @@
 #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>
@@ -65,6 +67,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 +506,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 +556,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);
 }
@@ -873,7 +882,7 @@ sp_image_update (SPObject *object, SPCtx *ctx, unsigned int flags)
                                }
                        }
        }
-
+       sp_image_set_curve((SPImage *) object); //creates a curve at the image's boundary for snapping
        sp_image_update_canvas_image ((SPImage *) object);
 }
 
@@ -1164,9 +1173,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;
+    }
 }
 
 /*
@@ -1355,6 +1385,56 @@ 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;
+    }
+    
+    SPCurve *c = sp_curve_new();
+
+    double const x = image->x.computed;
+    double const y = image->y.computed;
+    double const w = image->width.computed;
+    double const h = image->height.computed;
+    
+    sp_curve_moveto(c, x, y);
+    sp_curve_lineto(c, x + w, y);
+    sp_curve_lineto(c, x + w, y + h);
+    sp_curve_lineto(c, x, y + h);
+    sp_curve_lineto(c, x, y);
+
+    sp_curve_closepath_current(c);
+    
+    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++
index e0546d63d5057365374d855e0a43794204143e53..75194174ef11f8bba8ce67ab3ab8d6819f0f7293 100644 (file)
@@ -28,6 +28,7 @@ class SPImageClass;
 #include <gdk-pixbuf/gdk-pixbuf.h>
 #include "svg/svg-length.h"
 #include "sp-item.h"
+#include "display/display-forward.h"
 
 #define SP_IMAGE_HREF_MODIFIED_FLAG SP_OBJECT_USER_MODIFIED_FLAG_A
 
@@ -43,6 +44,8 @@ struct SPImage : public SPItem {
        unsigned int aspect_clip : 1;
        int trimx, trimy, trimwidth, trimheight;
        double viewx, viewy, viewwidth, viewheight;
+       
+       SPCurve *curve; // This curve is at the image's boundary for snapping
 
        gchar *href;
 #if ENABLE_LCMS
@@ -58,6 +61,8 @@ struct SPImageClass {
 
 GType sp_image_get_type (void);
 
+/* Return duplicate of curve or NULL */
+SPCurve *sp_image_get_curve (SPImage *image);
 
 
 #endif
index 9e836e84ae6e6287ede0a95f0467036d8c87ae3b..fbcc7b4a895b006c0538c9b5e917425a3d6596d9 100644 (file)
@@ -762,12 +762,17 @@ NR::Maybe<NR::Rect> sp_item_bbox_desktop(SPItem *item, SPItem::BBoxType type)
 static void sp_item_private_snappoints(SPItem const *item, SnapPointsIter p)
 {
     NR::Maybe<NR::Rect> bbox = item->getBounds(sp_item_i2d_affine(item));
-    /* Just a pair of opposite corners of the bounding box suffices given that we don't yet
+    /* Just the corners of the bounding box suffices given that we don't yet
        support angled guide lines. */
 
     if (bbox) {
-        *p = bbox->min();
-        *p = bbox->max();
+        NR::Point p1, p2;
+        p1 = bbox->min();
+        p2 = bbox->max();
+        *p = p1;
+        *p = NR::Point(p1[NR::X], p2[NR::Y]);
+        *p = p2;
+        *p = NR::Point(p1[NR::Y], p2[NR::X]);
     }
 }
 
index f1ce029f4f36b95c17bcb3c718e2bf9234dbd678..3ee5b5d61532b010717f520ef9391c54ec06f66d 100644 (file)
@@ -23,6 +23,7 @@
 #include "svg/svg.h"
 #include "sp-path.h"
 #include "sp-shape.h"
+#include "sp-image.h"
 #include "marker.h"
 #include "enums.h"
 #include "sp-text.h"
@@ -1713,6 +1714,10 @@ Path_for_item(SPItem *item, bool doTransformation, bool transformFull)
     {
         curve = SP_TEXT(item)->getNormalizedBpath();
     }
+    else if (SP_IS_IMAGE(item))
+    {
+        curve = sp_image_get_curve(SP_IMAGE(item));
+    }
     else
     {
         curve = NULL;