Skip to content

Commit 75fac2e

Browse files
committed
Negative dimensions will flip shapes again
Only applicable to shape mode `CORNER` Fixes #7353
1 parent cfc17d3 commit 75fac2e

File tree

8 files changed

+105
-19
lines changed

8 files changed

+105
-19
lines changed

src/core/helpers.js

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,35 +15,58 @@ function modeAdjust(a, b, c, d, mode) {
1515

1616
if (mode === constants.CORNER) {
1717

18-
// CORNER mode already corresponds to a bounding box (top-left corner, width, height)
19-
bbox = { x: a, y: b, w: c, h: d };
18+
// CORNER mode already corresponds to a bounding box (top-left corner, width, height).
19+
// Negative dimensions (width and/or height) result in 'flipping' the shape.
20+
if (c < 0) { c = -c; a -= c; } // Negative width: Move shape to the left (flip left)
21+
if (d < 0) { d = -d; b -= d; } // Negative height: Move shape up (flip up)
22+
bbox = {
23+
x: a,
24+
y: b,
25+
w: c,
26+
h: d
27+
};
2028

2129
} else if (mode === constants.CORNERS) {
2230

2331
// CORNERS mode uses two opposite corners, in any configuration.
2432
// Make sure to get the top left corner by using the minimum of the x and y coordniates.
25-
bbox = { x: Math.min(a, c), y: Math.min(b, d), w: c - a, h: d - b };
33+
bbox = {
34+
x: Math.min(a, c),
35+
y: Math.min(b, d),
36+
w: Math.abs(c - a),
37+
h: Math.abs(d - b)
38+
};
2639

2740
} else if (mode === constants.RADIUS) {
2841

2942
// RADIUS mode uses the center point and half the width and height.
3043
// c (half width) and d (half height) could be negative, so use the absolute value
3144
// in calculating the top left corner (x, y).
32-
bbox = { x: a - Math.abs(c), y: b - Math.abs(d), w: 2 * c, h: 2 * d };
45+
c = Math.abs(c);
46+
d = Math.abs(d);
47+
bbox = {
48+
x: a - c,
49+
y: b - d,
50+
w: 2 * c,
51+
h: 2 * d
52+
};
3353

3454
} else if (mode === constants.CENTER) {
3555

3656
// CENTER mode uses the center point, width and height.
3757
// c (width) and d (height) could be negative, so use the absolute value
38-
// in calculating the top-left corner (x,y).
39-
bbox = { x: a - Math.abs(c * 0.5), y: b - Math.abs(d * 0.5), w: c, h: d };
58+
// in calculating the top-left corner (x, y).
59+
c = Math.abs(c);
60+
d = Math.abs(d);
61+
bbox = {
62+
x: a - (c * 0.5),
63+
y: b - (d * 0.5),
64+
w: c,
65+
h: d
66+
};
4067

4168
}
4269

43-
// p5 supports negative width and heights for rectangles, ellipses and arcs
44-
bbox.w = Math.abs(bbox.w);
45-
bbox.h = Math.abs(bbox.h);
46-
4770
return bbox;
4871
}
4972

test/unit/visual/cases/shape_modes.js

Lines changed: 63 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ function shapeCorners(p5, shape, mode, x1, y1, x2, y2) {
1717
// Don't use abs(), so we get negative values as well
1818
let w = x2 - x1; // w
1919
let h = y2 - y1; // h
20+
// With mode CORNER, negative widths/heights result in mirrored/flipped shapes
21+
// In this case, adjust position so the shape is in line with the other cases
22+
if (w < 0) { x += (-w); } // Move right
23+
if (h < 0) { y += (-h); } // Move down
2024
x1 = x; y1 = y; x2 = w; y2 = h;
2125
} else if (mode === p5.CENTER) {
2226
// Find center
@@ -56,14 +60,15 @@ function shapeCorners(p5, shape, mode, x1, y1, x2, y2) {
5660
}
5761

5862

59-
/*
60-
Comprehensive test for rendering ellipse(), arc(), and rect()
61-
with the different ellipseMode() / rectMode() values: CORNERS, CORNER, CENTER, RADIUS.
62-
Each of the 3 shapes is tested with each of the 4 possible modes, resulting in 12 test.
63-
Each test renders the shape in 16 different coordinate configurations,
64-
testing combinations of positive and negative coordinate values.
65-
*/
6663
visualSuite('Shape Modes', function(...args) {
64+
/*
65+
Comprehensive test for rendering ellipse(), arc(), and rect()
66+
with the different ellipseMode() / rectMode() values: CORNERS, CORNER, CENTER, RADIUS.
67+
Each of the 3 shapes is tested with each of the 4 possible modes, resulting in 12 tests.
68+
Each test renders the shape in 16 different coordinate configurations,
69+
testing combinations of positive and negative coordinate values.
70+
*/
71+
6772
// Shapes to test
6873
const SHAPES = [ 'ellipse', 'arc', 'rect' ];
6974

@@ -113,6 +118,55 @@ visualSuite('Shape Modes', function(...args) {
113118
}); // End of: visualTest
114119
} // End of: MODES loop
115120

116-
}); // End of: Inner visualSuite
121+
}); // End of: visualSuite
117122
} // End of: SHAPES loop
118-
}); // End of: Outer visualSuite
123+
124+
125+
/*
126+
An extra test suite specific to shape mode CORNER and negative dimensions.
127+
Negative width should result in the shape flipped horizontally (to the left).
128+
Negative height should result in the shape flipped vertically (up).
129+
*/
130+
visualSuite('Negative dimensions', function() {
131+
visualTest('rect', function(p5, screenshot) {
132+
p5.createCanvas(50, 50);
133+
p5.translate(p5.width/2, p5.height/2);
134+
p5.rectMode(p5.CORNER);
135+
p5.rect(0, 0, 20, 10);
136+
p5.fill('red');
137+
p5.rect(0, 0, -20, 10);
138+
p5.fill('green');
139+
p5.rect(0, 0, 20, -10);
140+
p5.fill('blue');
141+
p5.rect(0, 0, -20, -10);
142+
screenshot();
143+
});
144+
visualTest('ellipse', function(p5, screenshot) {
145+
p5.createCanvas(50, 50);
146+
p5.translate(p5.width/2, p5.height/2);
147+
p5.ellipseMode(p5.CORNER);
148+
p5.ellipse(0, 0, 20, 10);
149+
p5.fill('red');
150+
p5.ellipse(0, 0, -20, 10);
151+
p5.fill('green');
152+
p5.ellipse(0, 0, 20, -10);
153+
p5.fill('blue');
154+
p5.ellipse(0, 0, -20, -10);
155+
screenshot();
156+
});
157+
visualTest('arc', function(p5, screenshot) {
158+
p5.createCanvas(50, 50);
159+
p5.translate(p5.width/2, p5.height/2);
160+
p5.ellipseMode(p5.CORNER);
161+
p5.arc(0, 0, 20, 10, 0, p5.PI + p5.HALF_PI);
162+
p5.fill('red');
163+
p5.arc(0, 0, -20, 10, 0, p5.PI + p5.HALF_PI);
164+
p5.fill('green');
165+
p5.arc(0, 0, 20, -10, 0, p5.PI + p5.HALF_PI);
166+
p5.fill('blue');
167+
p5.arc(0, 0, -20, -10, 0, p5.PI + p5.HALF_PI);
168+
screenshot();
169+
});
170+
});
171+
172+
});
1.06 KB
Loading
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"numScreenshots": 1
3+
}
1.2 KB
Loading
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"numScreenshots": 1
3+
}
405 Bytes
Loading
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"numScreenshots": 1
3+
}

0 commit comments

Comments
 (0)