summaryrefslogtreecommitdiffstats
path: root/src/splivarot.cpp
diff options
context:
space:
mode:
authorsu_v <suv-sf@users.sourceforge.net>2013-08-29 21:06:10 +0000
committer~suv <suv-sf@users.sourceforge.net>2013-08-29 21:06:10 +0000
commit4d331e73a76dce7d703716093923ca01b3cc5936 (patch)
treeb444657ba269b25f60684e66858a138b74fe240d /src/splivarot.cpp
parentFix compiler warnings (diff)
parentUpdating outdated test. Fixes bug #1202271. (diff)
downloadinkscape-4d331e73a76dce7d703716093923ca01b3cc5936.tar.gz
inkscape-4d331e73a76dce7d703716093923ca01b3cc5936.zip
merge from trunk (r12487)
(bzr r11668.1.75)
Diffstat (limited to 'src/splivarot.cpp')
-rw-r--r--src/splivarot.cpp126
1 files changed, 81 insertions, 45 deletions
diff --git a/src/splivarot.cpp b/src/splivarot.cpp
index d07de51e3..8a57fa98a 100644
--- a/src/splivarot.cpp
+++ b/src/splivarot.cpp
@@ -34,6 +34,7 @@
#include "style.h"
#include "document.h"
#include "document-undo.h"
+#include "layer-model.h"
#include "message-stack.h"
#include "selection.h"
#include "desktop-handles.h"
@@ -59,56 +60,67 @@ using Inkscape::DocumentUndo;
bool Ancetre(Inkscape::XML::Node *a, Inkscape::XML::Node *who);
-void sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb=SP_VERB_NONE, const Glib::ustring description="");
+void sp_selected_path_boolop(Inkscape::Selection *selection, SPDesktop *desktop, bool_op bop, const unsigned int verb=SP_VERB_NONE, const Glib::ustring description="");
void sp_selected_path_do_offset(SPDesktop *desktop, bool expand, double prefOffset);
void sp_selected_path_create_offset_object(SPDesktop *desktop, int expand, bool updating);
void
-sp_selected_path_union(SPDesktop *desktop)
+sp_selected_path_union(Inkscape::Selection *selection, SPDesktop *desktop)
{
- sp_selected_path_boolop(desktop, bool_op_union, SP_VERB_SELECTION_UNION, _("Union"));
+ sp_selected_path_boolop(selection, desktop, bool_op_union, SP_VERB_SELECTION_UNION, _("Union"));
}
void
-sp_selected_path_union_skip_undo(SPDesktop *desktop)
+sp_selected_path_union_skip_undo(Inkscape::Selection *selection, SPDesktop *desktop)
{
- sp_selected_path_boolop(desktop, bool_op_union, SP_VERB_NONE, _("Union"));
+ sp_selected_path_boolop(selection, desktop, bool_op_union, SP_VERB_NONE, _("Union"));
}
void
-sp_selected_path_intersect(SPDesktop *desktop)
+sp_selected_path_intersect(Inkscape::Selection *selection, SPDesktop *desktop)
{
- sp_selected_path_boolop(desktop, bool_op_inters, SP_VERB_SELECTION_INTERSECT, _("Intersection"));
+ sp_selected_path_boolop(selection, desktop, bool_op_inters, SP_VERB_SELECTION_INTERSECT, _("Intersection"));
}
void
-sp_selected_path_diff(SPDesktop *desktop)
+sp_selected_path_diff(Inkscape::Selection *selection, SPDesktop *desktop)
{
- sp_selected_path_boolop(desktop, bool_op_diff, SP_VERB_SELECTION_DIFF, _("Difference"));
+ sp_selected_path_boolop(selection, desktop, bool_op_diff, SP_VERB_SELECTION_DIFF, _("Difference"));
}
void
-sp_selected_path_diff_skip_undo(SPDesktop *desktop)
+sp_selected_path_diff_skip_undo(Inkscape::Selection *selection, SPDesktop *desktop)
{
- sp_selected_path_boolop(desktop, bool_op_diff, SP_VERB_NONE, _("Difference"));
+ sp_selected_path_boolop(selection, desktop, bool_op_diff, SP_VERB_NONE, _("Difference"));
}
void
-sp_selected_path_symdiff(SPDesktop *desktop)
+sp_selected_path_symdiff(Inkscape::Selection *selection, SPDesktop *desktop)
{
- sp_selected_path_boolop(desktop, bool_op_symdiff, SP_VERB_SELECTION_SYMDIFF, _("Exclusion"));
+ sp_selected_path_boolop(selection, desktop, bool_op_symdiff, SP_VERB_SELECTION_SYMDIFF, _("Exclusion"));
}
void
-sp_selected_path_cut(SPDesktop *desktop)
+sp_selected_path_cut(Inkscape::Selection *selection, SPDesktop *desktop)
{
- sp_selected_path_boolop(desktop, bool_op_cut, SP_VERB_SELECTION_CUT, _("Division"));
+ sp_selected_path_boolop(selection, desktop, bool_op_cut, SP_VERB_SELECTION_CUT, _("Division"));
}
void
-sp_selected_path_slice(SPDesktop *desktop)
+sp_selected_path_slice(Inkscape::Selection *selection, SPDesktop *desktop)
{
- sp_selected_path_boolop(desktop, bool_op_slice, SP_VERB_SELECTION_SLICE, _("Cut path"));
+ sp_selected_path_boolop(selection, desktop, bool_op_slice, SP_VERB_SELECTION_SLICE, _("Cut path"));
}
+// helper for printing error messages, regardless of whether we have a GUI or not
+// If desktop == NULL, errors will be shown on stderr
+static void
+boolop_display_error_message(SPDesktop *desktop, Glib::ustring const &msg)
+{
+ if (desktop) {
+ desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, msg);
+ } else {
+ g_printerr("%s\n", msg.c_str());
+ }
+}
// boolean operations PathVectors A,B -> PathVector result.
// This is derived from sp_selected_path_boolop
@@ -311,25 +323,24 @@ Geom::PathVector pathliv_to_pathvector(Path *pathliv){
// boolean operations on the desktop
// take the source paths from the file, do the operation, delete the originals and add the results
void
-sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb, const Glib::ustring description)
+sp_selected_path_boolop(Inkscape::Selection *selection, SPDesktop *desktop, bool_op bop, const unsigned int verb, const Glib::ustring description)
{
- Inkscape::Selection *selection = sp_desktop_selection(desktop);
-
+ SPDocument *doc = selection->layers()->getDocument();
GSList *il = (GSList *) selection->itemList();
// allow union on a single object for the purpose of removing self overlapse (svn log, revision 13334)
if ( (g_slist_length(il) < 2) && (bop != bool_op_union)) {
- desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Select <b>at least 2 paths</b> to perform a boolean operation."));
+ boolop_display_error_message(desktop, _("Select <b>at least 2 paths</b> to perform a boolean operation."));
return;
}
else if ( g_slist_length(il) < 1 ) {
- desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Select <b>at least 1 path</b> to perform a boolean union."));
+ boolop_display_error_message(desktop, _("Select <b>at least 1 path</b> to perform a boolean union."));
return;
}
if (g_slist_length(il) > 2) {
if (bop == bool_op_diff || bop == bool_op_cut || bop == bool_op_slice ) {
- desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Select <b>exactly 2 paths</b> to perform difference, division, or path cut."));
+ boolop_display_error_message(desktop, _("Select <b>exactly 2 paths</b> to perform difference, division, or path cut."));
return;
}
}
@@ -345,7 +356,7 @@ sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb
Inkscape::XML::Node *b = reinterpret_cast<SPObject *>(il->next->data)->getRepr();
if (a == NULL || b == NULL) {
- desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Unable to determine the <b>z-order</b> of the objects selected for difference, XOR, division, or path cut."));
+ boolop_display_error_message(desktop, _("Unable to determine the <b>z-order</b> of the objects selected for difference, XOR, division, or path cut."));
return;
}
@@ -360,7 +371,7 @@ sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb
// find their lowest common ancestor
Inkscape::XML::Node *dad = LCA(a, b);
if (dad == NULL) {
- desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Unable to determine the <b>z-order</b> of the objects selected for difference, XOR, division, or path cut."));
+ boolop_display_error_message(desktop, _("Unable to determine the <b>z-order</b> of the objects selected for difference, XOR, division, or path cut."));
return;
}
@@ -390,7 +401,7 @@ sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb
SPItem *item = SP_ITEM(l->data);
if (!SP_IS_SHAPE(item) && !SP_IS_TEXT(item) && !SP_IS_FLOWTEXT(item))
{
- desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("One of the objects is <b>not a path</b>, cannot perform boolean operation."));
+ boolop_display_error_message(desktop, _("One of the objects is <b>not a path</b>, cannot perform boolean operation."));
g_slist_free(il);
return;
}
@@ -465,11 +476,38 @@ sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb
theShapeB->ConvertToShape(theShape, origWind[curOrig]);
- if (theShapeA->numberOfEdges() == 0) {
- Shape *swap = theShapeB;
- theShapeB = theShapeA;
- theShapeA = swap;
- } else if (theShapeB->numberOfEdges() > 0) {
+ /* Due to quantization of the input shape coordinates, we may end up with A or B being empty.
+ * If this is a union or symdiff operation, we just use the non-empty shape as the result:
+ * A=0 => (0 or B) == B
+ * B=0 => (A or 0) == A
+ * A=0 => (0 xor B) == B
+ * B=0 => (A xor 0) == A
+ * If this is an intersection operation, we just use the empty shape as the result:
+ * A=0 => (0 and B) == 0 == A
+ * B=0 => (A and 0) == 0 == B
+ * If this a difference operation, and the upper shape (A) is empty, we keep B.
+ * If the lower shape (B) is empty, we still keep B, as it's empty:
+ * A=0 => (B - 0) == B
+ * B=0 => (0 - A) == 0 == B
+ *
+ * In any case, the output from this operation is stored in shape A, so we may apply
+ * the above rules simply by judicious use of swapping A and B where necessary.
+ */
+ bool zeroA = theShapeA->numberOfEdges() == 0;
+ bool zeroB = theShapeB->numberOfEdges() == 0;
+ if (zeroA || zeroB) {
+ // We might need to do a swap. Apply the above rules depending on operation type.
+ bool resultIsB = ((bop == bool_op_union || bop == bool_op_symdiff) && zeroA)
+ || ((bop == bool_op_inters) && zeroB)
+ || (bop == bool_op_diff);
+ if (resultIsB) {
+ // Swap A and B to use B as the result
+ Shape *swap = theShapeB;
+ theShapeB = theShapeA;
+ theShapeA = swap;
+ }
+ } else {
+ // Just do the Boolean operation as usual
// les elements arrivent en ordre inverse dans la liste
theShape->Booleen(theShapeB, theShapeA, bop);
Shape *swap = theShape;
@@ -631,8 +669,7 @@ sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb
{
SP_OBJECT(l->data)->deleteObject();
}
- DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_NONE,
- description);
+ DocumentUndo::done(doc, SP_VERB_NONE, description);
selection->clear();
delete res;
@@ -654,8 +691,7 @@ sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb
sorted = g_slist_sort(sorted, (GCompareFunc) sp_repr_compare_position);
- source = sp_desktop_document(desktop)->
- getObjectByRepr((Inkscape::XML::Node *)sorted->data);
+ source = doc->getObjectByRepr((Inkscape::XML::Node *)sorted->data);
g_slist_free(sorted);
}
@@ -695,7 +731,7 @@ sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb
g_slist_free(il);
// premultiply by the inverse of parent's repr
- SPItem *parent_item = SP_ITEM(sp_desktop_document(desktop)->getObjectByRepr(parent));
+ SPItem *parent_item = SP_ITEM(doc->getObjectByRepr(parent));
Geom::Affine local (parent_item->i2doc_affine());
gchar *transform = sp_svg_transform_write(local.inverse());
@@ -725,7 +761,7 @@ sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb
for (int i=0;i<nbRP;i++) {
gchar *d = resPath[i]->svg_dump_path();
- Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc();
+ Inkscape::XML::Document *xml_doc = doc->getReprDoc();
Inkscape::XML::Node *repr = xml_doc->createElement("svg:path");
repr->setAttribute("style", style);
if (mask)
@@ -771,7 +807,7 @@ sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb
} else {
gchar *d = res->svg_dump_path();
- Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc();
+ Inkscape::XML::Document *xml_doc = doc->getReprDoc();
Inkscape::XML::Node *repr = xml_doc->createElement("svg:path");
repr->setAttribute("style", style);
@@ -789,10 +825,10 @@ sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb
repr->setAttribute("id", id);
parent->appendChild(repr);
if (title) {
- sp_desktop_document(desktop)->getObjectByRepr(repr)->setTitle(title);
+ doc->getObjectByRepr(repr)->setTitle(title);
}
if (desc) {
- sp_desktop_document(desktop)->getObjectByRepr(repr)->setDesc(desc);
+ doc->getObjectByRepr(repr)->setDesc(desc);
}
repr->setPosition(pos > 0 ? pos : 0);
@@ -805,7 +841,7 @@ sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb
if (desc) g_free(desc);
if (verb != SP_VERB_NONE) {
- DocumentUndo::done(sp_desktop_document(desktop), verb, description);
+ DocumentUndo::done(doc, verb, description);
}
delete res;
@@ -1764,12 +1800,12 @@ sp_selected_path_do_offset(SPDesktop *desktop, bool expand, double prefOffset)
float o_width = 0;
float o_miter = 0;
JoinType o_join = join_straight;
- ButtType o_butt = butt_straight;
+ //ButtType o_butt = butt_straight;
{
SPStyle *i_style = item->style;
int jointype = i_style->stroke_linejoin.value;
- int captype = i_style->stroke_linecap.value;
+ //int captype = i_style->stroke_linecap.value;
o_width = i_style->stroke_width.computed;
@@ -1785,7 +1821,7 @@ sp_selected_path_do_offset(SPDesktop *desktop, bool expand, double prefOffset)
break;
}
- switch (captype) {
+ /*switch (captype) {
case SP_STROKE_LINECAP_SQUARE:
o_butt = butt_square;
break;
@@ -1795,7 +1831,7 @@ sp_selected_path_do_offset(SPDesktop *desktop, bool expand, double prefOffset)
default:
o_butt = butt_straight;
break;
- }
+ }*/
o_width = prefOffset;