summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEric Greveson <eric@greveson.co.uk>2013-08-08 16:01:03 +0000
committerEric Greveson <eric@greveson.co.uk>2013-08-08 16:01:03 +0000
commit2f7ea8f8ae067cbb3406169d22a84426cabd43f6 (patch)
treefaf3161eae3c1bf7509a34a6ad82e9d624e0ebfe /src
parentRemove missing files from POTFILES.in (diff)
downloadinkscape-2f7ea8f8ae067cbb3406169d22a84426cabd43f6.tar.gz
inkscape-2f7ea8f8ae067cbb3406169d22a84426cabd43f6.zip
Fix to do the "right thing" for difference/intersection boolean ops when
one or more input paths are truncated to zero-size by the quantization step (coordinate rounding). Previously this had only been fixed for union ops (which happened to work for exclusion (XOR) ops as well). (bzr r12472.1.1)
Diffstat (limited to 'src')
-rw-r--r--src/splivarot.cpp36
1 files changed, 31 insertions, 5 deletions
diff --git a/src/splivarot.cpp b/src/splivarot.cpp
index 356cf0161..6423129b9 100644
--- a/src/splivarot.cpp
+++ b/src/splivarot.cpp
@@ -277,11 +277,37 @@ sp_selected_path_boolop(Inkscape::Selection *selection, SPDesktop *desktop, bool
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;