diff options
| author | Eric Greveson <eric@greveson.co.uk> | 2013-08-08 16:01:03 +0000 |
|---|---|---|
| committer | Eric Greveson <eric@greveson.co.uk> | 2013-08-08 16:01:03 +0000 |
| commit | 2f7ea8f8ae067cbb3406169d22a84426cabd43f6 (patch) | |
| tree | faf3161eae3c1bf7509a34a6ad82e9d624e0ebfe /src | |
| parent | Remove missing files from POTFILES.in (diff) | |
| download | inkscape-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.cpp | 36 |
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; |
