diff options
author | 2016-06-29 16:22:27 -0700 | |
---|---|---|
committer | 2016-06-29 16:22:28 -0700 | |
commit | 82457c51176855b9be0b441010870093a6feb414 (patch) | |
tree | d00581f5984e6fd6cd150b53bb4af90d0d5df69f | |
parent | 6401217532e5357549988182b90bea28a86691e2 (diff) |
Handle post-record-time clipPath scaling
bug:29547149
Change-Id: I268210b240d2d8e08638114715f9622840fc02f7
-rw-r--r-- | libs/hwui/ClipArea.cpp | 27 | ||||
-rw-r--r-- | libs/hwui/ClipArea.h | 2 | ||||
-rw-r--r-- | libs/hwui/Rect.h | 7 | ||||
-rw-r--r-- | libs/hwui/tests/unit/ClipAreaTests.cpp | 59 |
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, ®ion); 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(), ®ion); + 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, ®ion); + 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, ®ion); + 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, ®ion); + EXPECT_TRUE(region.isRect()); + EXPECT_EQ(SkIRect::MakeLTRB(12, 26, 16, 32), region.getBounds()); +} + } // namespace uirenderer } // namespace android |