summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 48c9e2e)
raw | patch | inline | side by side (parent: 48c9e2e)
author | Josh Andler <scislac@gmail.com> | |
Thu, 4 Feb 2010 19:50:48 +0000 (11:50 -0800) | ||
committer | Josh Andler <scislac@gmail.com> | |
Thu, 4 Feb 2010 19:50:48 +0000 (11:50 -0800) |
diff --git a/src/enums.h b/src/enums.h
index 4d3c75c208e1f108b1f97720bf58cfbd788ed299..8b9dcc71f691ab39dbfb13d9cd0df8955fda1cb4 100644 (file)
--- a/src/enums.h
+++ b/src/enums.h
PREFS_SELECTION_LAYER_RECURSIVE = 2,
};
+/* clip/mask group enclosing behavior preference values */
+
+enum PrefsMaskobjectGrouping {
+ PREFS_MASKOBJECT_GROUPING_NONE = 0,
+ PREFS_MASKOBJECT_GROUPING_SEPARATE = 1,
+ PREFS_MASKOBJECT_GROUPING_ALL = 2,
+};
+
#endif
index e81d133c2dd9dc049790c801c7e8c72584e5719d..a5c6ae961609b839a04981a907df68585f8adfa0 100644 (file)
#include "ui/tool/control-point-selection.h"
#include "ui/tool/multi-path-manipulator.h"
+#include "enums.h"
+#include "sp-item-group.h"
+
// For clippath editing
#include "tools-switch.h"
#include "ui/tool/node-tool.h"
sp_edit_select_all_full(desktop, true, true);
}
-void sp_selection_group(SPDesktop *desktop)
-{
- if (desktop == NULL)
- return;
-
- SPDocument *doc = sp_desktop_document(desktop);
- Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc);
-
- Inkscape::Selection *selection = sp_desktop_selection(desktop);
-
- // Check if something is selected.
- if (selection->isEmpty()) {
- desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>some objects</b> to group."));
- return;
- }
-
- GSList const *l = (GSList *) selection->reprList();
-
- GSList *p = g_slist_copy((GSList *) l);
-
- selection->clear();
-
+void sp_selection_group_impl(GSList const *reprs_to_group, Inkscape::XML::Node *group, Inkscape::XML::Document *xml_doc, SPDocument *doc) {
+ GSList *p = g_slist_copy((GSList *) reprs_to_group);
+
p = g_slist_sort(p, (GCompareFunc) sp_repr_compare_position);
-
+
// Remember the position and parent of the topmost object.
gint topmost = ((Inkscape::XML::Node *) g_slist_last(p)->data)->position();
Inkscape::XML::Node *topmost_parent = ((Inkscape::XML::Node *) g_slist_last(p)->data)->parent();
-
- Inkscape::XML::Node *group = xml_doc->createElement("svg:g");
-
+
while (p) {
Inkscape::XML::Node *current = (Inkscape::XML::Node *) p->data;
// Move to the position of the topmost, reduced by the number of items deleted from topmost_parent
group->setPosition(topmost + 1);
+}
+
+void sp_selection_group(SPDesktop *desktop)
+{
+ if (desktop == NULL)
+ return;
+
+ SPDocument *doc = sp_desktop_document(desktop);
+ Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc);
+
+ Inkscape::Selection *selection = sp_desktop_selection(desktop);
+
+ // Check if something is selected.
+ if (selection->isEmpty()) {
+ desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>some objects</b> to group."));
+ return;
+ }
+
+ GSList const *l = (GSList *) selection->reprList();
+
+
+ Inkscape::XML::Node *group = xml_doc->createElement("svg:g");
+
+ sp_selection_group_impl(l, group, xml_doc, doc);
sp_document_done(sp_desktop_document(desktop), SP_VERB_SELECTION_GROUP,
_("Group"));
+ selection->clear();
selection->set(group);
Inkscape::GC::release(group);
}
@@ -2856,6 +2863,7 @@ sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_to_la
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
bool topmost = prefs->getBool("/options/maskobject/topmost", true);
bool remove_original = prefs->getBool("/options/maskobject/remove", true);
+ int grouping = prefs->getInt("/options/maskobject/grouping", PREFS_MASKOBJECT_GROUPING_NONE);
if (apply_to_layer) {
// all selected items are used for mask, which is applied to a layer
@@ -2901,6 +2909,36 @@ sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_to_la
g_slist_free(items);
items = NULL;
+
+ if (apply_to_items && grouping == PREFS_MASKOBJECT_GROUPING_ALL) {
+ // group all those objects into one group
+ // and apply mask to that
+ Inkscape::XML::Node *group = xml_doc->createElement("svg:g");
+
+ // make a note we should ungroup this when unsetting mask
+ group->setAttribute("inkscape:groupmode", "maskhelper");
+
+ GSList *reprs_to_group = NULL;
+
+ for (GSList *i = apply_to_items ; NULL != i ; i = i->next) {
+ reprs_to_group = g_slist_prepend(reprs_to_group, SP_OBJECT_REPR(i->data));
+ selection->remove(SP_OBJECT(i->data));
+ }
+ reprs_to_group = g_slist_reverse(reprs_to_group);
+
+ sp_selection_group_impl(reprs_to_group, group, xml_doc, doc);
+
+ g_slist_free(reprs_to_group);
+
+ // apply clip/mask only to newly created group
+ g_slist_free(apply_to_items);
+ apply_to_items = NULL;
+ apply_to_items = g_slist_prepend(apply_to_items, doc->getObjectByRepr(group));
+
+ selection->add(group);
+
+ Inkscape::GC::release(group);
+ }
gchar const *attributeName = apply_clip_path ? "clip-path" : "mask";
for (GSList *i = apply_to_items; NULL != i; i = i->next) {
@@ -2925,7 +2963,34 @@ sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_to_la
g_slist_free(mask_items_dup);
mask_items_dup = NULL;
- SP_OBJECT_REPR(i->data)->setAttribute(attributeName, g_strdup_printf("url(#%s)", mask_id));
+ Inkscape::XML::Node *current = SP_OBJECT_REPR(i->data);
+ // Node to apply mask to
+ Inkscape::XML::Node *apply_mask_to = current;
+
+ if (grouping == PREFS_MASKOBJECT_GROUPING_SEPARATE) {
+ // enclose current node in group, and apply crop/mask on that
+ Inkscape::XML::Node *group = xml_doc->createElement("svg:g");
+ // make a note we should ungroup this when unsetting mask
+ group->setAttribute("inkscape:groupmode", "maskhelper");
+
+ Inkscape::XML::Node *spnew = current->duplicate(xml_doc);
+ gint position = current->position();
+ selection->remove(current);
+ current->parent()->appendChild(group);
+ sp_repr_unparent(current);
+ group->appendChild(spnew);
+ group->setPosition(position);
+
+ // Apply clip/mask to group instead
+ apply_mask_to = group;
+
+ selection->add(group);
+ Inkscape::GC::release(spnew);
+ Inkscape::GC::release(group);
+ }
+
+ apply_mask_to->setAttribute(attributeName, g_strdup_printf("url(#%s)", mask_id));
+
}
g_slist_free(mask_items);
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
bool remove_original = prefs->getBool("/options/maskobject/remove", true);
+ bool ungroup_masked = prefs->getBool("/options/maskobject/ungrouping", true);
sp_document_ensure_up_to_date(doc);
gchar const *attributeName = apply_clip_path ? "clip-path" : "mask";
std::map<SPObject*,SPItem*> referenced_objects;
+
+ GSList *items_to_ungroup = NULL;
+
// SPObject* refers to a group containing the clipped path or mask itself,
// whereas SPItem* refers to the item being clipped or masked
for (GSList const *i = selection->itemList(); NULL != i; i = i->next) {
}
SP_OBJECT_REPR(i->data)->setAttribute(attributeName, "none");
+
+ if (ungroup_masked && SP_IS_GROUP(i->data)) {
+ // if we had previously enclosed masked object in group,
+ // add it to list so we can ungroup it later
+ SPGroup *item = SP_GROUP(i->data);
+
+ // ungroup only groups we created when setting clip/mask
+ if (item->layerMode() == SPGroup::MASK_HELPER) {
+ items_to_ungroup = g_slist_prepend(items_to_ungroup, item);
+ }
+
+ }
}
// restore mask objects into a document
g_slist_free(items_to_move);
}
+
+ // ungroup marked groups added when setting mask
+ for (GSList *i = items_to_ungroup ; NULL != i ; i = i->next) {
+ selection->remove(SP_GROUP(i->data));
+ GSList *children = NULL;
+ sp_item_group_ungroup(SP_GROUP(i->data), &children, false);
+ selection->addList(children);
+ g_slist_free(children);
+ }
+
+ g_slist_free(items_to_ungroup);
if (apply_clip_path)
sp_document_done(doc, SP_VERB_OBJECT_UNSET_CLIPPATH, _("Release clipping path"));
index 60d64ced9c8c3e181ab4fddde046c33fa920ec00..e06c32e725e422c459e53e32ac8a7d6d8ed429db 100644 (file)
void sp_selection_tile(SPDesktop *desktop, bool apply = true);
void sp_selection_untile(SPDesktop *desktop);
+//void sp_selection_group_impl(GSList const *reprs_to_group, Inkscape::XML::Node *group, Inkscape::XML::Document *xml_doc, SPDocument *doc);
void sp_selection_group(SPDesktop *desktop);
void sp_selection_ungroup(SPDesktop *desktop);
diff --git a/src/sp-item-group.cpp b/src/sp-item-group.cpp
index a773bd4a24df825b54f987dce126f3dace9c072a..5884277521c9a24fcfac82d519363029c005d18d 100644 (file)
--- a/src/sp-item-group.cpp
+++ b/src/sp-item-group.cpp
@@ -258,6 +258,8 @@ sp_group_write (SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XM
const char *value;
if ( group->_layer_mode == SPGroup::LAYER ) {
value = "layer";
+ } else if ( group->_layer_mode == SPGroup::MASK_HELPER ) {
+ value = "maskhelper";
} else if ( flags & SP_OBJECT_WRITE_ALL ) {
value = "group";
} else {
case SP_ATTR_INKSCAPE_GROUPMODE:
if ( value && !strcmp(value, "layer") ) {
group->setLayerMode(SPGroup::LAYER);
+ } else if ( value && !strcmp(value, "maskhelper") ) {
+ group->setLayerMode(SPGroup::MASK_HELPER);
} else {
group->setLayerMode(SPGroup::GROUP);
}
if ( _layer_mode != mode ) {
if ( mode == LAYER ) {
sp_document_add_resource(SP_OBJECT_DOCUMENT(this), "layer", this);
- } else {
+ } else if ( _layer_mode == LAYER ) {
sp_document_remove_resource(SP_OBJECT_DOCUMENT(this), "layer", this);
}
_layer_mode = mode;
diff --git a/src/sp-item-group.h b/src/sp-item-group.h
index 65a51055a79aab462eb760c4a9d1a7cff0dcce82..932241a42f6b8eaae25ed798764c01dd45ef7e93 100644 (file)
--- a/src/sp-item-group.h
+++ b/src/sp-item-group.h
class CGroup;
struct SPGroup : public SPLPEItem {
- enum LayerMode { GROUP, LAYER };
+ enum LayerMode { GROUP, LAYER, MASK_HELPER };
LayerMode _layer_mode;
std::map<unsigned int, LayerMode> _display_modes;
index 961c7dff7f43d7426fd2c4a517f5677991edbef7..b2257a3fe098e70c2a548379dac789253d66e197 100644 (file)
_mask_mask_remove.init ( _("Remove clippath/mask object after applying"), "/options/maskobject/remove", true);
_page_mask.add_line(true, "", _mask_mask_remove, "",
_("After applying, remove the object used as the clipping path or mask from the drawing"));
+
+ _page_mask.add_group_header( _("Before applying clippath/mask:"));
+
+ _mask_grouping_none.init( _("Do not group clipped/masked objects"), "/options/maskobject/grouping", PREFS_MASKOBJECT_GROUPING_NONE, true, 0);
+ _mask_grouping_separate.init( _("Enclose every clipped/masked object in its own group"), "/options/maskobject/grouping", PREFS_MASKOBJECT_GROUPING_SEPARATE, false, &_mask_grouping_none);
+ _mask_grouping_all.init( _("Put all clipped/masked objects into one group"), "/options/maskobject/grouping", PREFS_MASKOBJECT_GROUPING_ALL, false, &_mask_grouping_none);
+
+ _page_mask.add_line(true, "", _mask_grouping_none, "",
+ _("Apply clippath/mask to every object"));
+
+ _page_mask.add_line(true, "", _mask_grouping_separate, "",
+ _("Apply clippath/mask to groups containing single object"));
+
+ _page_mask.add_line(true, "", _mask_grouping_all, "",
+ _("Apply clippath/mask to group containing all objects"));
+
+ _page_mask.add_group_header( _("After releasing clippath/mask:"));
+
+ _mask_ungrouping.init ( _("Ungroup automatically created groups"), "/options/maskobject/ungrouping", true);
+ _page_mask.add_line(true, "", _mask_ungrouping, "",
+ _("Ungroup groups created when setting clip/mask"));
+
this->AddPage(_page_mask, _("Clippaths and masks"), PREFS_PAGE_MASKS);
}
index 49c84728759316d852c783bfdf5ed112e01c3a91..e3f76b753492d48b145ea6632a0b86da80fb6000 100644 (file)
PrefCheckButton _mask_mask_on_top;
PrefCheckButton _mask_mask_remove;
+ PrefRadioButton _mask_grouping_none, _mask_grouping_separate, _mask_grouping_all;
+ PrefCheckButton _mask_ungrouping;
PrefRadioButton _blur_quality_best, _blur_quality_better, _blur_quality_normal, _blur_quality_worse, _blur_quality_worst;
PrefRadioButton _filter_quality_best, _filter_quality_better, _filter_quality_normal, _filter_quality_worse, _filter_quality_worst;