From 5271cd656d5e935ca2f55b6b61a4f3aedee22fd5 Mon Sep 17 00:00:00 2001 From: knutux Date: Wed, 22 Mar 2006 06:22:39 +0000 Subject: [PATCH] Mask/Clippath transformations on masking/unmasking --- src/selection-chemistry.cpp | 60 ++++++++++++++++++++++++------------- src/sp-clippath.cpp | 10 +++++-- src/sp-clippath.h | 2 +- src/sp-mask.cpp | 10 +++++-- src/sp-mask.h | 2 +- 5 files changed, 58 insertions(+), 26 deletions(-) diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp index ba0d89850..e7e3ec4a3 100644 --- a/src/selection-chemistry.cpp +++ b/src/selection-chemistry.cpp @@ -64,7 +64,7 @@ #include "file.h" #include "layer-fns.h" #include "context-fns.h" -#include +#include using NR::X; using NR::Y; @@ -2295,7 +2295,7 @@ sp_selection_set_mask(bool apply_clip_path, bool apply_to_layer) if (apply_to_layer) { // all selected items are used for mask, which is applied to a layer - apply_to_items = g_slist_prepend (apply_to_items, SP_OBJECT_REPR(desktop->currentLayer())); + apply_to_items = g_slist_prepend (apply_to_items, desktop->currentLayer()); for (GSList *i = items; i != NULL; i = i->next) { Inkscape::XML::Node *dup = (SP_OBJECT_REPR (i->data))->duplicate(); @@ -2318,12 +2318,12 @@ sp_selection_set_mask(bool apply_clip_path, bool apply_to_layer) } for (i = i->next; i != NULL; i = i->next) { - apply_to_items = g_slist_prepend (apply_to_items, SP_OBJECT_REPR (i->data)); + apply_to_items = g_slist_prepend (apply_to_items, i->data); } } else { GSList *i = NULL; for (i = items; NULL != i->next; i = i->next) { - apply_to_items = g_slist_prepend (apply_to_items, SP_OBJECT_REPR (i->data)); + apply_to_items = g_slist_prepend (apply_to_items, i->data); } Inkscape::XML::Node *dup = (SP_OBJECT_REPR (i->data))->duplicate(); @@ -2336,20 +2336,35 @@ sp_selection_set_mask(bool apply_clip_path, bool apply_to_layer) } g_slist_free (items); + items = NULL; - const gchar *mask_id = NULL; - if (apply_clip_path) { - mask_id = sp_clippath_create(mask_items, document); - } else { - mask_id = sp_mask_create(mask_items, document); - } - g_slist_free (mask_items); - gchar const* attributeName = apply_clip_path ? "clip-path" : "mask"; for (GSList *i = apply_to_items; NULL != i; i = i->next) { - ((Inkscape::XML::Node *)i->data)->setAttribute(attributeName, g_strdup_printf("url(#%s)", mask_id)); + SPItem *item = reinterpret_cast(i->data); + // inverted object transform should be applied to a mask object, + // as mask is calculated in user space (after applying transform) + NR::Matrix maskTransform (item->transform.inverse()); + + GSList *mask_items_dup = NULL; + for (GSList *mask_item = mask_items; NULL != mask_item; mask_item = mask_item->next) { + Inkscape::XML::Node *dup = reinterpret_cast(mask_item->data)->duplicate(); + mask_items_dup = g_slist_prepend (mask_items_dup, dup); + } + + const gchar *mask_id = NULL; + if (apply_clip_path) { + mask_id = sp_clippath_create(mask_items_dup, document, &maskTransform); + } else { + mask_id = sp_mask_create(mask_items_dup, document, &maskTransform); + } + + g_slist_free (mask_items_dup); + mask_items_dup = NULL; + + SP_OBJECT_REPR(i->data)->setAttribute(attributeName, g_strdup_printf("url(#%s)", mask_id)); } + g_slist_free (mask_items); g_slist_free (apply_to_items); sp_document_done (document); @@ -2373,7 +2388,7 @@ void sp_selection_unset_mask(bool apply_clip_path) { sp_document_ensure_up_to_date(document); gchar const* attributeName = apply_clip_path ? "clip-path" : "mask"; - std::set referenced_objects; + std::map referenced_objects; for (GSList const*i = selection->itemList(); NULL != i; i = i->next) { if (remove_original) { // remember referenced mask/clippath, so orphaned masks can be moved back to document @@ -2386,9 +2401,9 @@ void sp_selection_unset_mask(bool apply_clip_path) { uri_ref = item->mask_ref; } - // collect distinct mask object - if (NULL != uri_ref && NULL != uri_ref->getObject() && referenced_objects.end() == referenced_objects.find(uri_ref->getObject())) { - referenced_objects.insert(uri_ref->getObject()); + // collect distinct mask object (and associate with item to apply transform) + if (NULL != uri_ref && NULL != uri_ref->getObject()) { + referenced_objects[uri_ref->getObject()] = item; } } @@ -2396,8 +2411,8 @@ void sp_selection_unset_mask(bool apply_clip_path) { } // restore mask objects into a document - for ( std::set::iterator it = referenced_objects.begin() ; it != referenced_objects.end() ; ++it) { - SPObject *obj = (*it); + for ( std::map::iterator it = referenced_objects.begin() ; it != referenced_objects.end() ; ++it) { + SPObject *obj = (*it).first; GSList *items_to_move = NULL; for (SPObject *child = sp_object_first_child(obj) ; child != NULL; child = SP_OBJECT_NEXT(child) ) { Inkscape::XML::Node *copy = SP_OBJECT_REPR(child)->duplicate(); @@ -2410,8 +2425,13 @@ void sp_selection_unset_mask(bool apply_clip_path) { } for (GSList *i = items_to_move; NULL != i; i = i->next) { - desktop->currentLayer()->appendChildRepr((Inkscape::XML::Node *)i->data); + SPItem *item = SP_ITEM(desktop->currentLayer()->appendChildRepr((Inkscape::XML::Node *)i->data)); selection->add((Inkscape::XML::Node *)i->data); + + // transform mask, so it is moved the same spot there mask was applied + NR::Matrix transform (item->transform); + transform *= (*it).second->transform; + sp_item_write_transform(item, SP_OBJECT_REPR(item), transform); } g_slist_free (items_to_move); diff --git a/src/sp-clippath.cpp b/src/sp-clippath.cpp index 33feea8ce..35e073879 100644 --- a/src/sp-clippath.cpp +++ b/src/sp-clippath.cpp @@ -371,7 +371,7 @@ sp_clippath_view_list_remove(SPClipPathView *list, SPClipPathView *view) // Create a mask element (using passed elements), add it to const gchar * -sp_clippath_create (GSList *reprs, SPDocument *document) +sp_clippath_create (GSList *reprs, SPDocument *document, NR::Matrix const* applyTransform) { Inkscape::XML::Node *defsrepr = SP_OBJECT_REPR (SP_DOCUMENT_DEFS (document)); @@ -384,7 +384,13 @@ sp_clippath_create (GSList *reprs, SPDocument *document) for (GSList *it = reprs; it != NULL; it = it->next) { Inkscape::XML::Node *node = (Inkscape::XML::Node *)(it->data); - clip_path_object->appendChildRepr(node); + SPItem *item = SP_ITEM(clip_path_object->appendChildRepr(node)); + + if (NULL != applyTransform) { + NR::Matrix transform (item->transform); + transform *= (*applyTransform); + sp_item_write_transform(item, SP_OBJECT_REPR(item), transform); + } } Inkscape::GC::release(repr); diff --git a/src/sp-clippath.h b/src/sp-clippath.h index 0f977a3e8..8f20d7880 100644 --- a/src/sp-clippath.h +++ b/src/sp-clippath.h @@ -59,6 +59,6 @@ void sp_clippath_hide(SPClipPath *cp, unsigned int key); void sp_clippath_set_bbox(SPClipPath *cp, unsigned int key, NRRect *bbox); void sp_clippath_get_bbox(SPClipPath *cp, NRRect *bbox, NR::Matrix const &transform, unsigned const flags); -const gchar *sp_clippath_create (GSList *reprs, SPDocument *document); +const gchar *sp_clippath_create (GSList *reprs, SPDocument *document, NR::Matrix const* applyTransform); #endif diff --git a/src/sp-mask.cpp b/src/sp-mask.cpp index 773169d68..55b678293 100644 --- a/src/sp-mask.cpp +++ b/src/sp-mask.cpp @@ -269,7 +269,7 @@ sp_mask_write (SPObject *object, Inkscape::XML::Node *repr, guint flags) // Create a mask element (using passed elements), add it to const gchar * -sp_mask_create (GSList *reprs, SPDocument *document) +sp_mask_create (GSList *reprs, SPDocument *document, NR::Matrix const* applyTransform) { Inkscape::XML::Node *defsrepr = SP_OBJECT_REPR (SP_DOCUMENT_DEFS (document)); @@ -282,7 +282,13 @@ sp_mask_create (GSList *reprs, SPDocument *document) for (GSList *it = reprs; it != NULL; it = it->next) { Inkscape::XML::Node *node = (Inkscape::XML::Node *)(it->data); - mask_object->appendChildRepr(node); + SPItem *item = SP_ITEM(mask_object->appendChildRepr(node)); + + if (NULL != applyTransform) { + NR::Matrix transform (item->transform); + transform *= (*applyTransform); + sp_item_write_transform(item, SP_OBJECT_REPR(item), transform); + } } Inkscape::GC::release(repr); diff --git a/src/sp-mask.h b/src/sp-mask.h index b17ac8399..621029b98 100644 --- a/src/sp-mask.h +++ b/src/sp-mask.h @@ -60,6 +60,6 @@ void sp_mask_hide (SPMask *mask, unsigned int key); void sp_mask_set_bbox (SPMask *mask, unsigned int key, NRRect *bbox); -const gchar *sp_mask_create (GSList *reprs, SPDocument *document); +const gchar *sp_mask_create (GSList *reprs, SPDocument *document, NR::Matrix const* applyTransform); #endif -- 2.30.2