summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 769e2eb)
raw | patch | inline | side by side (parent: 769e2eb)
author | buliabyak <buliabyak@users.sourceforge.net> | |
Sun, 19 Mar 2006 23:19:10 +0000 (23:19 +0000) | ||
committer | buliabyak <buliabyak@users.sourceforge.net> | |
Sun, 19 Mar 2006 23:19:10 +0000 (23:19 +0000) |
13 files changed:
diff --git a/src/menus-skeleton.h b/src/menus-skeleton.h
index 0ecfb7cefcfc45b4458abce994f3a4dd52546f5d..7d8a5803dd00c76dea39716c6c207ffbcdc4d59e 100644 (file)
--- a/src/menus-skeleton.h
+++ b/src/menus-skeleton.h
" <verb verb-id=\"SelectionGroup\" />\n"
" <verb verb-id=\"SelectionUnGroup\" />\n"
" <separator/>\n"
+" <submenu name=\"" N_("Cli_p") "\">\n"
+" <verb verb-id=\"ObjectSetClipPath\" />\n"
+" <verb verb-id=\"ObjectUnSetClipPath\" />\n"
+" </submenu>\n"
+" <submenu name=\"" N_("Mas_k") "\">\n"
+" <verb verb-id=\"ObjectSetMask\" />\n"
+" <verb verb-id=\"ObjectUnSetMask\" />\n"
+" </submenu>\n"
+" <separator/>\n"
" <verb verb-id=\"SelectionRaise\" />\n"
" <verb verb-id=\"SelectionLower\" />\n"
" <verb verb-id=\"SelectionToFront\" />\n"
index 688a080fabafbbf65f73a297a078814d6c874538..5873622dd332c87485040d41a7a642613a108954 100644 (file)
" <group id=\"kbselection\" inlayer=\"1\" onlyvisible=\"1\" onlysensitive=\"1\" />\n"
" <group id=\"createbitmap\" minsize=\"250\"/>\n"
" <group id=\"compassangledisplay\" value=\"0\"/>\n"
+" <group id=\"maskobject\" topmost=\"1\" remove=\"1\"/>\n"
" </group>\n"
"\n"
" <group id=\"extensions\" show-effects-menu=\"0\">"
index cd6fb2823d161ed8379b4a1e4682c9fb268f796c..a92cb1a73d8eff147d5aafe8e19f50067c0b811a 100644 (file)
* Frank Felfe <innerspace@iname.com>
* MenTaLguY <mental@rydia.net>
* bulia byak <buliabyak@users.sf.net>
+ * Andrius R. <knutux@gmail.com>
*
- * Copyright (C) 1999-2005 authors
+ * Copyright (C) 1999-2006 authors
* Copyright (C) 2001-2002 Ximian, Inc.
*
* Released under GNU GPL, read the file 'COPYING' for more information
#include "sp-namedview.h"
#include "prefs-utils.h"
#include "sp-offset.h"
+#include "sp-clippath.h"
+#include "sp-mask.h"
#include "file.h"
#include "layer-fns.h"
#include "context-fns.h"
+#include <set>
using NR::X;
using NR::Y;
}
void
-sp_undo(SPDesktop *desktop, SPDocument *doc)
+sp_undo(SPDesktop *desktop, SPDocument *)
{
if (!sp_document_undo(SP_DT_DOCUMENT(desktop)))
desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Nothing to undo."));
}
void
-sp_redo(SPDesktop *desktop, SPDocument *doc)
+sp_redo(SPDesktop *desktop, SPDocument *)
{
if (!sp_document_redo(SP_DT_DOCUMENT(desktop)))
desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Nothing to redo."));
g_free (filepath);
}
+/**
+ * \brief sp_selection_set_mask
+ *
+ * This function creates a mask or clipPath from selection
+ * Two different modes:
+ * if applyToLayer, all selection is moved to DEFS as mask/clippath
+ * and is applied to current layer
+ * otherwise, topmost object is used as mask for other objects
+ * If \a apply_clip_path parameter is true, clipPath is created, otherwise mask
+ *
+ */
+void
+sp_selection_set_mask(bool apply_clip_path, bool apply_to_layer)
+{
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ if (desktop == NULL)
+ return;
+
+ SPDocument *document = SP_DT_DOCUMENT(desktop);
+
+ Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+
+ // check if something is selected
+ bool is_empty = selection->isEmpty();
+ if ( apply_to_layer && is_empty) {
+ desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to create mask from."));
+ return;
+ } else if (!apply_to_layer && ( is_empty || NULL == selection->itemList()->next )) {
+ desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select mask object and <b>object(s)</b> to apply mask to."));
+ return;
+ }
+
+ sp_document_ensure_up_to_date(document);
+
+ GSList *items = g_slist_copy((GSList *) selection->itemList());
+
+ items = g_slist_sort (items, (GCompareFunc) sp_object_compare_position);
+
+ // create a list of duplicates
+ GSList *mask_items = NULL;
+ GSList *apply_to_items = NULL;
+ bool topmost = prefs_get_int_attribute ("options.maskobject", "topmost", 1);
+ bool remove_original = prefs_get_int_attribute ("options.maskobject", "remove", 1);
+
+ 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()));
+
+ for (GSList *i = items; i != NULL; i = i->next) {
+ Inkscape::XML::Node *dup = (SP_OBJECT_REPR (i->data))->duplicate();
+ mask_items = g_slist_prepend (mask_items, dup);
+
+ if (remove_original) {
+ SPObject *item = SP_OBJECT (i->data);
+ item->deleteObject (false);
+ }
+ }
+ } else if (!topmost) {
+ // topmost item is used as a mask, which is applied to other items in a selection
+ GSList *i = items;
+ Inkscape::XML::Node *dup = (SP_OBJECT_REPR (i->data))->duplicate();
+ mask_items = g_slist_prepend (mask_items, dup);
+
+ if (remove_original) {
+ SPObject *item = SP_OBJECT (i->data);
+ item->deleteObject (false);
+ }
+
+ for (i = i->next; i != NULL; i = i->next) {
+ apply_to_items = g_slist_prepend (apply_to_items, SP_OBJECT_REPR (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));
+ }
+
+ Inkscape::XML::Node *dup = (SP_OBJECT_REPR (i->data))->duplicate();
+ mask_items = g_slist_prepend (mask_items, dup);
+
+ if (remove_original) {
+ SPObject *item = SP_OBJECT (i->data);
+ item->deleteObject (false);
+ }
+ }
+
+ g_slist_free (items);
+
+ 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));
+ }
+
+ g_slist_free (apply_to_items);
+
+ sp_document_done (document);
+}
+
+void sp_selection_unset_mask(bool apply_clip_path) {
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ if (desktop == NULL)
+ return;
+
+ SPDocument *document = SP_DT_DOCUMENT(desktop);
+ Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+
+ // check if something is selected
+ if (selection->isEmpty()) {
+ desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to remove mask from."));
+ return;
+ }
+
+ bool remove_original = prefs_get_int_attribute ("options.maskobject", "remove", 1);
+ sp_document_ensure_up_to_date(document);
+
+ gchar const* attributeName = apply_clip_path ? "clip-path" : "mask";
+ std::set<SPObject*> 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
+ SPItem *item = reinterpret_cast<SPItem *>(i->data);
+ Inkscape::URIReference *uri_ref = NULL;
+
+ if (apply_clip_path) {
+ uri_ref = item->clip_ref;
+ } else {
+ uri_ref = item->mask_ref;
+ }
+
+ if (NULL != uri_ref && referenced_objects.end() == referenced_objects.find(uri_ref->getObject())) {
+ referenced_objects.insert(uri_ref->getObject());
+ }
+ }
+
+ SP_OBJECT_REPR(i->data)->setAttribute(attributeName, "none");
+ }
+
+ for ( std::set<SPObject*>::iterator it = referenced_objects.begin() ; it != referenced_objects.end() ; ++it) {
+ SPObject *obj = (*it);
+ if (!obj->isReferenced()) {
+ 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();
+ items_to_move = g_slist_prepend (items_to_move, copy);
+ }
+
+ obj->deleteObject(false);
+
+ for (GSList *i = items_to_move; NULL != i; i = i->next) {
+ desktop->currentLayer()->appendChildRepr((Inkscape::XML::Node *)i->data);
+ }
+
+ g_slist_free (items_to_move);
+ }
+ }
+
+ sp_document_done (document);
+}
/*
Local Variables:
index 9fbeaa9ecd0844441ea6013bb11e708cc8ffe4b0..df8b699317726bb29dbaf709ef42cfd7f0451696 100644 (file)
void sp_selection_create_bitmap_copy ();
+void sp_selection_set_mask(bool apply_clip_path, bool apply_to_layer);
+void sp_selection_unset_mask(bool apply_clip_path);
+
/* selection cycling */
typedef enum
diff --git a/src/sp-clippath.cpp b/src/sp-clippath.cpp
index 086b6dcfa3084f040af83d8265a4dae0944a8442..33feea8ce2eef50669b8a78841becde558822f69 100644 (file)
--- a/src/sp-clippath.cpp
+++ b/src/sp-clippath.cpp
#include "enums.h"
#include "attributes.h"
#include "document.h"
+#include "document-private.h"
#include "sp-item.h"
#include "sp-clippath.h"
return list;
}
+// Create a mask element (using passed elements), add it to <defs>
+const gchar *
+sp_clippath_create (GSList *reprs, SPDocument *document)
+{
+ Inkscape::XML::Node *defsrepr = SP_OBJECT_REPR (SP_DOCUMENT_DEFS (document));
+
+ Inkscape::XML::Node *repr = sp_repr_new ("svg:clipPath");
+ repr->setAttribute("clipPathUnits", "userSpaceOnUse");
+
+ defsrepr->appendChild(repr);
+ const gchar *id = repr->attribute("id");
+ SPObject *clip_path_object = document->getObjectById(id);
+
+ for (GSList *it = reprs; it != NULL; it = it->next) {
+ Inkscape::XML::Node *node = (Inkscape::XML::Node *)(it->data);
+ clip_path_object->appendChildRepr(node);
+ }
+
+ Inkscape::GC::release(repr);
+ return id;
+}
/*
Local Variables:
diff --git a/src/sp-clippath.h b/src/sp-clippath.h
index 0a8b92fa908820cdd315a9b13377e9acd9a4ac48..0f977a3e8dbe533a5b6bb0f4b0ccd8dd5f0897cd 100644 (file)
--- a/src/sp-clippath.h
+++ b/src/sp-clippath.h
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);
+
#endif
diff --git a/src/sp-mask.cpp b/src/sp-mask.cpp
index 456dadc5fc29d709c524c1957bf34cf800f6f388..773169d68847d2edfc342c3a55596ed022082831 100644 (file)
--- a/src/sp-mask.cpp
+++ b/src/sp-mask.cpp
#include "enums.h"
#include "attributes.h"
#include "document.h"
+#include "document-private.h"
#include "sp-item.h"
#include "sp-mask.h"
return repr;
}
+// Create a mask element (using passed elements), add it to <defs>
+const gchar *
+sp_mask_create (GSList *reprs, SPDocument *document)
+{
+ Inkscape::XML::Node *defsrepr = SP_OBJECT_REPR (SP_DOCUMENT_DEFS (document));
+
+ Inkscape::XML::Node *repr = sp_repr_new ("svg:mask");
+ repr->setAttribute("maskUnits", "userSpaceOnUse");
+
+ defsrepr->appendChild(repr);
+ const gchar *mask_id = repr->attribute("id");
+ SPObject *mask_object = document->getObjectById(mask_id);
+
+ for (GSList *it = reprs; it != NULL; it = it->next) {
+ Inkscape::XML::Node *node = (Inkscape::XML::Node *)(it->data);
+ mask_object->appendChildRepr(node);
+ }
+
+ Inkscape::GC::release(repr);
+ return mask_id;
+}
+
NRArenaItem *
sp_mask_show (SPMask *mask, NRArena *arena, unsigned int key)
{
diff --git a/src/sp-mask.h b/src/sp-mask.h
index 23239f55dd4bd52cc75af23c583c7efbddbeaf71..b17ac83997a2e231d187edeadc4790361346b9ac 100644 (file)
--- a/src/sp-mask.h
+++ b/src/sp-mask.h
void sp_mask_set_bbox (SPMask *mask, unsigned int key, NRRect *bbox);
+const gchar *sp_mask_create (GSList *reprs, SPDocument *document);
+
#endif
diff --git a/src/sp-object.h b/src/sp-object.h
index e853de097907055d0623422677b10fb8de7212d1..4879e5bea0fe3e7d71c4db7e2ff40f737dd7b79e 100644 (file)
--- a/src/sp-object.h
+++ b/src/sp-object.h
}
}
+ /** @brief Check if object is referenced by any other object.
+ */
+ bool isReferenced() { return ( _total_hrefcount > 0 ); }
+
/** @brief Deletes an object.
*
* Detaches the object's repr, and optionally sends notification that the object has been
index 54977ac05d897555fee6c661e769a1c4cdf156d1..b90ed8d986df30b27c805e9c1b4fde911fc69c58 100644 (file)
_misc_overs_bitmap.init("options.bitmapoversample", "value", labels, values, num_items, 1);
_page_misc.add_line( false, _("Oversample bitmaps:"), _misc_overs_bitmap, "", "", false);
+ _page_misc.add_group_header( _("Clipping and masking:"));
+ _misc_mask_on_top.init ( _("Use the topmost selected object as a clipping path or mask"), "options.maskobject", "topmost", true);
+ _page_misc.add_line(true, "", _misc_mask_on_top, "",
+ _("Uncheck this to use the bottom selected object as the clipping path or mask"));
+ _misc_mask_remove.init ( _("Remove clipping path or mask after applying"), "options.maskobject", "remove", true);
+ _page_misc.add_line(true, "", _misc_mask_remove, "",
+ _("Affter applying, remove the object used as the clipping path or mask from the drawing"));
+
this->AddPage(_page_misc, _("Misc"), PREFS_PAGE_MISC);
}
index de2010f125d7503c8ac1e836a691b59612a2c5b7..af3dfa44b03ace56e9cc2ae49f29d850ed7c7a5a 100644 (file)
PrefSpinButton _misc_export, _misc_recent, _misc_simpl;
PrefCheckButton _misc_imp_bitmap, _misc_comment, _misc_scripts;
PrefCombo _misc_overs_bitmap;
+ PrefCheckButton _misc_mask_on_top;
+ PrefCheckButton _misc_mask_remove;
int _max_dialog_width;
int _max_dialog_height;
diff --git a/src/verbs.cpp b/src/verbs.cpp
index f262b93275668381b322ca53a06e18895ac5d886..84da8703bb902394a6467a9379eefc8ae7bb4235 100644 (file)
--- a/src/verbs.cpp
+++ b/src/verbs.cpp
}
sp_document_done(SP_DT_DOCUMENT(dt));
break;
+ case SP_VERB_OBJECT_SET_MASK:
+ sp_selection_set_mask(false, false);
+ break;
+ case SP_VERB_OBJECT_UNSET_MASK:
+ sp_selection_unset_mask(false);
+ break;
+ case SP_VERB_OBJECT_SET_CLIPPATH:
+ sp_selection_set_mask(true, false);
+ break;
+ case SP_VERB_OBJECT_UNSET_CLIPPATH:
+ sp_selection_unset_mask(true);
+ break;
default:
break;
}
new ObjectVerb(SP_VERB_OBJECT_FLIP_VERTICAL, "ObjectFlipVertically",
N_("Flip _Vertical"), N_("Flips selected objects vertically"),
"object_flip_ver"),
+ new ObjectVerb(SP_VERB_OBJECT_SET_MASK, "ObjectSetMask", N_("_Set"),
+ N_("Apply mask to selection (using the topmost object as mask)"), NULL),
+ new ObjectVerb(SP_VERB_OBJECT_UNSET_MASK, "ObjectUnSetMask", N_("_Release"),
+ 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_UNSET_CLIPPATH, "ObjectUnSetClipPath", N_("_Release"),
+ N_("Remove clipping path from selection"), NULL),
/* Tools */
new ContextVerb(SP_VERB_CONTEXT_SELECT, "DrawSelect", N_("Select"),
diff --git a/src/verbs.h b/src/verbs.h
index acc6d7d17a9fdee7a9f4b7a069ebd5a25f9d12e6..426b4295f0236b6b38d1118caa552fb3d33e06d1 100644 (file)
--- a/src/verbs.h
+++ b/src/verbs.h
SP_VERB_OBJECT_FLOWTEXT_TO_TEXT,
SP_VERB_OBJECT_FLIP_HORIZONTAL,
SP_VERB_OBJECT_FLIP_VERTICAL,
+ SP_VERB_OBJECT_SET_MASK,
+ SP_VERB_OBJECT_UNSET_MASK,
+ SP_VERB_OBJECT_SET_CLIPPATH,
+ SP_VERB_OBJECT_UNSET_CLIPPATH,
/* Tools */
SP_VERB_CONTEXT_SELECT,
SP_VERB_CONTEXT_NODE,