y = dy * dz;
}
+/**
+ * Set the contents of the rect to be the bounding rect around each of the corners, mapped by the
+ * matrix.
+ *
+ * NOTE: an empty rect to an arbitrary matrix isn't guaranteed to have an empty output, since that's
+ * important for conservative bounds estimation (e.g. rotate45Matrix.mapRect of Rect(0, 10) should
+ * result in non-empty.
+ */
void Matrix4::mapRect(Rect& r) const {
- if (isIdentity() || r.isEmpty()) return;
+ if (isIdentity()) return;
if (isSimple()) {
MUL_ADD_STORE(r.left, data[kScaleX], data[kTranslateX]);
using namespace android::uirenderer;
-TEST(Matrix, mapRect) {
+TEST(Matrix, mapRect_emptyScaleSkew) {
// Skew, so we don't hit identity/translate/simple fast paths
- Matrix4 matrix;
- matrix.skew(0.1f, 0.1f);
+ Matrix4 scaleMatrix;
+ scaleMatrix.loadScale(10, 10, 1);
+ scaleMatrix.skew(0.1f, 0.1f);
// non-zero empty rect, so sorting x/y would make rect non-empty
- Rect empty(100, 100, -100, -100);
+ Rect empty(15, 20, 15, 100);
ASSERT_TRUE(empty.isEmpty());
- matrix.mapRect(empty);
- EXPECT_TRUE(empty.isEmpty())
- << "Empty rect should always remain empty, regardless of mapping.";
+ scaleMatrix.mapRect(empty);
+ EXPECT_EQ(Rect(170, 215, 250, 1015), empty);
+ EXPECT_FALSE(empty.isEmpty())
+ << "Empty 'line' rect doesn't remain empty when skewed.";
+}
+
+TEST(Matrix, mapRect_emptyRotate) {
+ // Skew, so we don't hit identity/translate/simple fast paths
+ Matrix4 skewMatrix;
+ skewMatrix.loadRotate(45);
+
+ // non-zero empty rect, so sorting x/y would make rect non-empty
+ Rect lineRect(0, 100);
+ ASSERT_TRUE(lineRect.isEmpty());
+ skewMatrix.mapRect(lineRect);
+ EXPECT_FALSE(lineRect.isEmpty())
+ << "Empty 'line' rect doesn't remain empty when rotated.";
}