summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Chris Craik <ccraik@google.com> 2016-06-29 16:22:27 -0700
committer Chris Craik <ccraik@google.com> 2016-06-29 16:22:28 -0700
commit82457c51176855b9be0b441010870093a6feb414 (patch)
treed00581f5984e6fd6cd150b53bb4af90d0d5df69f
parent6401217532e5357549988182b90bea28a86691e2 (diff)
Handle post-record-time clipPath scaling
bug:29547149 Change-Id: I268210b240d2d8e08638114715f9622840fc02f7
-rw-r--r--libs/hwui/ClipArea.cpp27
-rw-r--r--libs/hwui/ClipArea.h2
-rw-r--r--libs/hwui/Rect.h7
-rw-r--r--libs/hwui/tests/unit/ClipAreaTests.cpp59
4 files changed, 89 insertions, 6 deletions
diff --git a/libs/hwui/ClipArea.cpp b/libs/hwui/ClipArea.cpp
index fe6823925083..39b8d3de9c75 100644
--- a/libs/hwui/ClipArea.cpp
+++ b/libs/hwui/ClipArea.cpp
@@ -464,10 +464,7 @@ const ClipBase* ClipArea::serializeIntersectedClip(LinearAllocator& allocator,
}
case ClipMode::Region:
other = getRegion(recordedClip);
-
- // TODO: handle non-translate transforms properly!
- other.translate(recordedClipTransform.getTranslateX(),
- recordedClipTransform.getTranslateY());
+ applyTransformToRegion(recordedClipTransform, &other);
}
ClipRegion* regionClip = allocator.create<ClipRegion>();
@@ -527,11 +524,29 @@ void ClipArea::applyClip(const ClipBase* clip, const Matrix4& transform) {
}
} else {
SkRegion region(getRegion(clip));
- // TODO: handle non-translate transforms properly!
- region.translate(transform.getTranslateX(), transform.getTranslateY());
+ applyTransformToRegion(transform, &region);
clipRegion(region, SkRegion::kIntersect_Op);
}
}
+void ClipArea::applyTransformToRegion(const Matrix4& transform, SkRegion* region) {
+ if (transform.isSimple() && !transform.isPureTranslate()) {
+ // handle matrices with scale manually by mapping each rect
+ SkRegion other;
+ SkRegion::Iterator it(*region);
+ while (!it.done()) {
+ Rect rect(it.rect());
+ transform.mapRect(rect);
+ rect.roundOut();
+ other.op(rect.left, rect.top, rect.right, rect.bottom, SkRegion::kUnion_Op);
+ it.next();
+ }
+ region->swap(other);
+ } else {
+ // TODO: handle non-translate transforms properly!
+ region->translate(transform.getTranslateX(), transform.getTranslateY());
+ }
+}
+
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/ClipArea.h b/libs/hwui/ClipArea.h
index 6eb2eef5a5f9..53d9d03a3629 100644
--- a/libs/hwui/ClipArea.h
+++ b/libs/hwui/ClipArea.h
@@ -179,6 +179,8 @@ public:
const ClipBase* recordedClip, const Matrix4& recordedClipTransform);
void applyClip(const ClipBase* recordedClip, const Matrix4& recordedClipTransform);
+ static void applyTransformToRegion(const Matrix4& transform, SkRegion* region);
+
private:
void enterRectangleMode();
void rectangleModeClipRectWithTransform(const Rect& r, const mat4* transform, SkRegion::Op op);
diff --git a/libs/hwui/Rect.h b/libs/hwui/Rect.h
index de4fa55bb508..5786668addc5 100644
--- a/libs/hwui/Rect.h
+++ b/libs/hwui/Rect.h
@@ -73,6 +73,13 @@ public:
bottom(height) {
}
+ inline Rect(const SkIRect& rect):
+ left(rect.fLeft),
+ top(rect.fTop),
+ right(rect.fRight),
+ bottom(rect.fBottom) {
+ }
+
inline Rect(const SkRect& rect):
left(rect.fLeft),
top(rect.fTop),
diff --git a/libs/hwui/tests/unit/ClipAreaTests.cpp b/libs/hwui/tests/unit/ClipAreaTests.cpp
index 54ca68d63dbe..afabd359ed45 100644
--- a/libs/hwui/tests/unit/ClipAreaTests.cpp
+++ b/libs/hwui/tests/unit/ClipAreaTests.cpp
@@ -275,5 +275,64 @@ TEST(ClipArea, serializeIntersectedClip_snap) {
}
}
+TEST(ClipArea, serializeIntersectedClip_scale) {
+ ClipArea area(createClipArea());
+ area.setClip(0, 0, 400, 400);
+ LinearAllocator allocator;
+
+ SkPath circlePath;
+ circlePath.addCircle(50, 50, 50);
+
+ ClipRegion recordedClip;
+ recordedClip.region.setPath(circlePath, SkRegion(SkIRect::MakeWH(100, 100)));
+ recordedClip.rect = Rect(100, 100);
+
+ Matrix4 translateScale;
+ translateScale.loadTranslate(100, 100, 0);
+ translateScale.scale(2, 2, 1);
+ auto resolvedClip = area.serializeIntersectedClip(allocator, &recordedClip, translateScale);
+
+ ASSERT_NE(nullptr, resolvedClip);
+ EXPECT_EQ(ClipMode::Region, resolvedClip->mode);
+ EXPECT_EQ(Rect(100, 100, 300, 300), resolvedClip->rect);
+ auto clipRegion = reinterpret_cast<const ClipRegion*>(resolvedClip);
+ EXPECT_EQ(SkIRect::MakeLTRB(100, 100, 300, 300), clipRegion->region.getBounds());
+}
+
+TEST(ClipArea, applyTransformToRegion_identity) {
+ SkRegion region(SkIRect::MakeLTRB(1, 2, 3, 4));
+ ClipArea::applyTransformToRegion(Matrix4::identity(), &region);
+ EXPECT_TRUE(region.isRect());
+ EXPECT_EQ(SkIRect::MakeLTRB(1, 2, 3, 4), region.getBounds());
+}
+
+TEST(ClipArea, applyTransformToRegion_translate) {
+ SkRegion region(SkIRect::MakeLTRB(1, 2, 3, 4));
+ Matrix4 transform;
+ transform.loadTranslate(10, 20, 0);
+ ClipArea::applyTransformToRegion(transform, &region);
+ EXPECT_TRUE(region.isRect());
+ EXPECT_EQ(SkIRect::MakeLTRB(11, 22, 13, 24), region.getBounds());
+}
+
+TEST(ClipArea, applyTransformToRegion_scale) {
+ SkRegion region(SkIRect::MakeLTRB(1, 2, 3, 4));
+ Matrix4 transform;
+ transform.loadScale(2, 3, 1);
+ ClipArea::applyTransformToRegion(transform, &region);
+ EXPECT_TRUE(region.isRect());
+ EXPECT_EQ(SkIRect::MakeLTRB(2, 6, 6, 12), region.getBounds());
+}
+
+TEST(ClipArea, applyTransformToRegion_translateScale) {
+ SkRegion region(SkIRect::MakeLTRB(1, 2, 3, 4));
+ Matrix4 transform;
+ transform.translate(10, 20);
+ transform.scale(2, 3, 1);
+ ClipArea::applyTransformToRegion(transform, &region);
+ EXPECT_TRUE(region.isRect());
+ EXPECT_EQ(SkIRect::MakeLTRB(12, 26, 16, 32), region.getBounds());
+}
+
} // namespace uirenderer
} // namespace android