diff options
| author | Liam P. White <inkscapebronyat-signgmaildotcom> | 2014-06-14 18:51:11 +0000 |
|---|---|---|
| committer | Liam P. White <inkscapebronyat-signgmaildotcom> | 2014-06-14 18:51:11 +0000 |
| commit | eb4d7e1225a2e1e5a5d1da8d0ab784632bc77291 (patch) | |
| tree | fc11d1a0d8e6e59982a0b49ccce5b1e074fde169 /src | |
| parent | Update to experimental r13402 (diff) | |
| download | inkscape-eb4d7e1225a2e1e5a5d1da8d0ab784632bc77291.tar.gz inkscape-eb4d7e1225a2e1e5a5d1da8d0ab784632bc77291.zip | |
Add clip group option from Ponyscape
(bzr r13090.1.83)
Diffstat (limited to 'src')
| -rw-r--r-- | src/interface.cpp | 11 | ||||
| -rw-r--r-- | src/interface.h | 1 | ||||
| -rw-r--r-- | src/selection-chemistry.cpp | 112 | ||||
| -rw-r--r-- | src/selection-chemistry.h | 1 | ||||
| -rw-r--r-- | src/ui/dialog/objects.cpp | 12 | ||||
| -rw-r--r-- | src/verbs.cpp | 5 | ||||
| -rw-r--r-- | src/verbs.h | 1 |
7 files changed, 139 insertions, 4 deletions
diff --git a/src/interface.cpp b/src/interface.cpp index 1cbeb44a3..e47cff598 100644 --- a/src/interface.cpp +++ b/src/interface.cpp @@ -1756,6 +1756,13 @@ void ContextMenu::MakeItemMenu (void) } mi->show(); append(*mi); + + /*SSet Clip Group */ + mi = Gtk::manage(new Gtk::MenuItem(_("Create Clip G_roup"),1)); + mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::CreateGroupClip)); + mi->set_sensitive(TRUE); + mi->show(); + append(*mi); /* Set Clip */ mi = Gtk::manage(new Gtk::MenuItem(_("Set Cl_ip"), 1)); @@ -1867,6 +1874,10 @@ void ContextMenu::ReleaseMask(void) sp_selection_unset_mask(_desktop, false); } +void ContextMenu::CreateGroupClip(void) +{ + sp_selection_set_clipgroup(_desktop); +} void ContextMenu::SetClip(void) { diff --git a/src/interface.h b/src/interface.h index 215a3bfc9..a4eedf9db 100644 --- a/src/interface.h +++ b/src/interface.h @@ -187,6 +187,7 @@ class ContextMenu : public Gtk::Menu void SelectSameStrokeStyle(void); void SelectSameObjectType(void); void ItemCreateLink(void); + void CreateGroupClip(void); void SetMask(void); void ReleaseMask(void); void SetClip(void); diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp index a350dd7a7..d2f6d692a 100644 --- a/src/selection-chemistry.cpp +++ b/src/selection-chemistry.cpp @@ -3661,6 +3661,118 @@ void sp_selection_create_bitmap_copy(SPDesktop *desktop) g_free(filepath); } +/* Creates a mask or clipPath from selection. + * What is a clip group? + * A clip group is a tangled mess of XML that allows an object inside a group + * to clip the entire group using a few <use>s and generally irritating me. + */ + +void sp_selection_set_clipgroup(SPDesktop *desktop) +{ + if (desktop == NULL) { + return; + } + SPDocument* doc = sp_desktop_document(desktop); + Inkscape::XML::Document *xml_doc = doc->getReprDoc(); + + Inkscape::Selection *selection = sp_desktop_selection(desktop); + if (selection->isEmpty()) { + desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to create clippath or mask from.")); + return; + } + + GSList const *l = const_cast<GSList *>(selection->reprList()); + + GSList *p = g_slist_copy(const_cast<GSList *>(l)); + + p = g_slist_sort(p, (GCompareFunc) sp_repr_compare_position); + + selection->clear(); + + gint topmost = (static_cast<Inkscape::XML::Node *>(g_slist_last(p)->data))->position(); + Inkscape::XML::Node *topmost_parent = (static_cast<Inkscape::XML::Node *>(g_slist_last(p)->data))->parent(); + + Inkscape::XML::Node *inner = xml_doc->createElement("svg:g"); + inner->setAttribute("inkscape:label", "Clip"); + + while (p) { + Inkscape::XML::Node *current = static_cast<Inkscape::XML::Node *>(p->data); + + if (current->parent() == topmost_parent) { + Inkscape::XML::Node *spnew = current->duplicate(xml_doc); + sp_repr_unparent(current); + inner->appendChild(spnew); + Inkscape::GC::release(spnew); + topmost --; // only reduce count for those items deleted from topmost_parent + } else { // move it to topmost_parent first + GSList *temp_clip = NULL; + + // At this point, current may already have no item, due to its being a clone whose original is already moved away + // So we copy it artificially calculating the transform from its repr->attr("transform") and the parent transform + gchar const *t_str = current->attribute("transform"); + Geom::Affine item_t(Geom::identity()); + if (t_str) + sp_svg_transform_read(t_str, &item_t); + item_t *= SP_ITEM(doc->getObjectByRepr(current->parent()))->i2doc_affine(); + // FIXME: when moving both clone and original from a transformed group (either by + // grouping into another parent, or by cut/paste) the transform from the original's + // parent becomes embedded into original itself, and this affects its clones. Fix + // this by remembering the transform diffs we write to each item into an array and + // then, if this is clone, looking up its original in that array and pre-multiplying + // it by the inverse of that original's transform diff. + + sp_selection_copy_one(current, item_t, &temp_clip, xml_doc); + sp_repr_unparent(current); + + // paste into topmost_parent (temporarily) + GSList *copied = sp_selection_paste_impl(doc, doc->getObjectByRepr(topmost_parent), &temp_clip); + if (temp_clip) g_slist_free(temp_clip); + if (copied) { // if success, + // take pasted object (now in topmost_parent) + Inkscape::XML::Node *in_topmost = static_cast<Inkscape::XML::Node *>(copied->data); + // make a copy + Inkscape::XML::Node *spnew = in_topmost->duplicate(xml_doc); + // remove pasted + sp_repr_unparent(in_topmost); + // put its copy into group + inner->appendChild(spnew); + Inkscape::GC::release(spnew); + g_slist_free(copied); + } + } + p = g_slist_remove(p, current); + } + + Inkscape::XML::Node *outer = xml_doc->createElement("svg:g"); + outer->appendChild(inner); + topmost_parent->appendChild(outer); + outer->setPosition(topmost + 1); + + Inkscape::XML::Node *clone = xml_doc->createElement("svg:use"); + clone->setAttribute("x", "0", false); + clone->setAttribute("y", "0", false); + clone->setAttribute("xlink:href", g_strdup_printf("#%s", inner->attribute("id")), false); + + clone->setAttribute("inkscape:transform-center-x", inner->attribute("inkscape:transform-center-x"), false); + clone->setAttribute("inkscape:transform-center-y", inner->attribute("inkscape:transform-center-y"), false); + + const Geom::Affine maskTransform(Geom::Affine::identity()); + GSList *templist = NULL; + + templist = g_slist_append(templist, clone); + // add the new clone to the top of the original's parent + gchar const *mask_id = SPClipPath::create(templist, doc, &maskTransform); + + g_slist_free(templist); + + outer->setAttribute("clip-path", g_strdup_printf("url(#%s)", mask_id)); + + Inkscape::GC::release(clone); + + selection->set(outer); + DocumentUndo::done(doc, SP_VERB_OBJECT_SET_CLIPPATH, _("Create Clip Group")); +} + /** * Creates a mask or clipPath from selection. * Two different modes: diff --git a/src/selection-chemistry.h b/src/selection-chemistry.h index d76a67a9d..baa530806 100644 --- a/src/selection-chemistry.h +++ b/src/selection-chemistry.h @@ -156,6 +156,7 @@ void sp_document_get_export_hints (SPDocument * doc, Glib::ustring &filename, fl void sp_selection_create_bitmap_copy (SPDesktop *desktop); +void sp_selection_set_clipgroup(SPDesktop *desktop); void sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_to_layer); void sp_selection_unset_mask(SPDesktop *desktop, bool apply_clip_path); diff --git a/src/ui/dialog/objects.cpp b/src/ui/dialog/objects.cpp index 85583a0e7..2d558daae 100644 --- a/src/ui/dialog/objects.cpp +++ b/src/ui/dialog/objects.cpp @@ -106,7 +106,7 @@ enum { BUTTON_LOCK_ALL, BUTTON_UNLOCK_ALL, BUTTON_SETCLIP, -// BUTTON_CLIPGROUP, + BUTTON_CLIPGROUP, // BUTTON_SETINVCLIP, BUTTON_UNSETCLIP, BUTTON_SETMASK, @@ -269,7 +269,7 @@ Gtk::MenuItem& ObjectsPanel::_addPopupItem( SPDesktop *desktop, unsigned int cod } if ( action ) { - label = action->name; + // label = action->name; } } } @@ -1257,6 +1257,10 @@ bool ObjectsPanel::_executeAction() _fireAction( SP_VERB_LAYER_UNLOCK_ALL ); } break; + case BUTTON_CLIPGROUP: + { + _fireAction ( SP_VERB_OBJECT_CREATE_CLIP_GROUP ); + } case BUTTON_SETCLIP: { _fireAction( SP_VERB_OBJECT_SET_CLIPPATH ); @@ -1935,8 +1939,8 @@ ObjectsPanel::ObjectsPanel() : _popupMenu.append(*Gtk::manage(new Gtk::SeparatorMenuItem())); _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_SET_CLIPPATH, 0, "Set Clip", (int)BUTTON_SETCLIP ) ); - //not implemented - //_watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_CREATE_CLIP_GROUP, 0, "Create Clip Group", (int)BUTTON_CLIPGROUP ) ); + + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_CREATE_CLIP_GROUP, 0, "Create Clip Group", (int)BUTTON_CLIPGROUP ) ); //will never be implemented //_watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_SET_INVERSE_CLIPPATH, 0, "Set Inverse Clip", (int)BUTTON_SETINVCLIP ) ); diff --git a/src/verbs.cpp b/src/verbs.cpp index 73613ab9e..f0a49a81a 100644 --- a/src/verbs.cpp +++ b/src/verbs.cpp @@ -1568,6 +1568,9 @@ void ObjectVerb::perform( SPAction *action, void *data) case SP_VERB_OBJECT_SET_CLIPPATH: sp_selection_set_mask(dt, true, false); break; + case SP_VERB_OBJECT_CREATE_CLIP_GROUP: + sp_selection_set_clipgroup(dt); + break; case SP_VERB_OBJECT_EDIT_CLIPPATH: sp_selection_edit_clip_or_mask(dt, true); break; @@ -2717,6 +2720,8 @@ Verb *Verb::_base_verbs[] = { N_("Remove mask from selection"), NULL), new ObjectVerb(SP_VERB_OBJECT_SET_CLIPPATH, "ObjectSetClipPath", N_("_Set"), N_("Apply clipping path to selection (using the topmost object as clipping path)"), NULL), + new ObjectVerb(SP_VERB_OBJECT_CREATE_CLIP_GROUP, "ObjectCreateClipGroup", N_("Create Cl_ip Group"), + N_("Creates a clip group using the selected objects as a base"), NULL), new ObjectVerb(SP_VERB_OBJECT_EDIT_CLIPPATH, "ObjectEditClipPath", N_("_Edit"), N_("Edit clipping path"), INKSCAPE_ICON("path-clip-edit")), new ObjectVerb(SP_VERB_OBJECT_UNSET_CLIPPATH, "ObjectUnSetClipPath", N_("_Release"), diff --git a/src/verbs.h b/src/verbs.h index 821c9ee82..84d31fe42 100644 --- a/src/verbs.h +++ b/src/verbs.h @@ -175,6 +175,7 @@ enum { SP_VERB_OBJECT_EDIT_MASK, SP_VERB_OBJECT_UNSET_MASK, SP_VERB_OBJECT_SET_CLIPPATH, + SP_VERB_OBJECT_CREATE_CLIP_GROUP, SP_VERB_OBJECT_EDIT_CLIPPATH, SP_VERB_OBJECT_UNSET_CLIPPATH, /* Tag */ |
