Merge lp:~7-eric/inkscape/boolop-fix into lp:~inkscape.dev/inkscape/trunk

Proposed by Eric Greveson
Status: Merged
Merged at revision: 12475
Proposed branch: lp:~7-eric/inkscape/boolop-fix
Merge into: lp:~inkscape.dev/inkscape/trunk
Diff against target: 46 lines (+31/-5)
1 file modified
src/splivarot.cpp (+31/-5)
To merge this branch: bzr merge lp:~7-eric/inkscape/boolop-fix
Reviewer Review Type Date Requested Status
Alvin Penner Approve
su_v (community) Approve
Review via email: mp+179223@code.launchpad.net

Description of the change

Fix for Bug #1209281. "Difference" and "Intersection" Boolean operations should now behave in a reasonable way when one or more input shapes is small enough that the automatic quantization step (before the Boolean operation takes place) shrinks it to zero. "Union" and "Exclusion" operations behave as before (already correct).

To post a comment you must log in.
Revision history for this message
su_v (suv-lp) wrote :

I can't review the proposed code itself, but based on tests (r12472+diff on OS X 10.7.5) with files from related bug reports I approve: no regression or unexpected results encountered.

review: Approve
Revision history for this message
Alvin Penner (apenner) wrote :

looks good to me, thanks!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/splivarot.cpp'
2--- src/splivarot.cpp 2013-07-04 14:01:44 +0000
3+++ src/splivarot.cpp 2013-08-08 16:13:45 +0000
4@@ -277,11 +277,37 @@
5
6 theShapeB->ConvertToShape(theShape, origWind[curOrig]);
7
8- if (theShapeA->numberOfEdges() == 0) {
9- Shape *swap = theShapeB;
10- theShapeB = theShapeA;
11- theShapeA = swap;
12- } else if (theShapeB->numberOfEdges() > 0) {
13+ // Due to quantization of the input shape coordinates, we may end up with A or B being empty.
14+ // If this is a union or symdiff operation, we just use the non-empty shape as the result:
15+ // A=0 => (0 or B) == B
16+ // B=0 => (A or 0) == A
17+ // A=0 => (0 xor B) == B
18+ // B=0 => (A xor 0) == A
19+ // If this is an intersection operation, we just use the empty shape as the result:
20+ // A=0 => (0 and B) == 0 == A
21+ // B=0 => (A and 0) == 0 == B
22+ // If this a difference operation, and the upper shape (A) is empty, we keep B.
23+ // If the lower shape (B) is empty, we still keep B, as it's empty:
24+ // A=0 => (B - 0) == B
25+ // B=0 => (0 - A) == 0 == B
26+ //
27+ // In any case, the output from this operation is stored in shape A, so we may apply
28+ // the above rules simply by judicious use of swapping A and B where necessary.
29+ bool zeroA = theShapeA->numberOfEdges() == 0;
30+ bool zeroB = theShapeB->numberOfEdges() == 0;
31+ if (zeroA || zeroB) {
32+ // We might need to do a swap. Apply the above rules depending on operation type.
33+ bool resultIsB = ((bop == bool_op_union || bop == bool_op_symdiff) && zeroA)
34+ || ((bop == bool_op_inters) && zeroB)
35+ || (bop == bool_op_diff);
36+ if (resultIsB) {
37+ // Swap A and B to use B as the result
38+ Shape *swap = theShapeB;
39+ theShapeB = theShapeA;
40+ theShapeA = swap;
41+ }
42+ } else {
43+ // Just do the Boolean operation as usual
44 // les elements arrivent en ordre inverse dans la liste
45 theShape->Booleen(theShapeB, theShapeA, bop);
46 Shape *swap = theShape;