From f76f0d94b4b87bb6c1ba98e14d120aac94e415d0 Mon Sep 17 00:00:00 2001 From: dvlierop2 Date: Tue, 26 Jun 2007 21:07:31 +0000 Subject: [PATCH] implementing snapping to images --- src/object-snapper.cpp | 44 ++++++++++++--------- src/sp-image.cpp | 88 ++++++++++++++++++++++++++++++++++++++++-- src/sp-image.h | 5 +++ src/sp-item.cpp | 11 ++++-- src/splivarot.cpp | 5 +++ 5 files changed, 128 insertions(+), 25 deletions(-) diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp index 8d5b30dff..a904bd93b 100644 --- a/src/object-snapper.cpp +++ b/src/object-snapper.cpp @@ -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::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)); diff --git a/src/sp-image.cpp b/src/sp-image.cpp index d710c109e..6ff6bb806 100644 --- a/src/sp-image.cpp +++ b/src/sp-image.cpp @@ -21,6 +21,7 @@ //#define GDK_PIXBUF_ENABLE_BACKEND 1 //#include #include "display/nr-arena-image.h" +#include //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 #include "xml/quote.h" #include @@ -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++ diff --git a/src/sp-image.h b/src/sp-image.h index e0546d63d..75194174e 100644 --- a/src/sp-image.h +++ b/src/sp-image.h @@ -28,6 +28,7 @@ class SPImageClass; #include #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 diff --git a/src/sp-item.cpp b/src/sp-item.cpp index 9e836e84a..fbcc7b4a8 100644 --- a/src/sp-item.cpp +++ b/src/sp-item.cpp @@ -762,12 +762,17 @@ NR::Maybe sp_item_bbox_desktop(SPItem *item, SPItem::BBoxType type) static void sp_item_private_snappoints(SPItem const *item, SnapPointsIter p) { NR::Maybe 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]); } } diff --git a/src/splivarot.cpp b/src/splivarot.cpp index f1ce029f4..3ee5b5d61 100644 --- a/src/splivarot.cpp +++ b/src/splivarot.cpp @@ -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; -- 2.30.2