Loading libs/hwui/ClipArea.cpp +21 −6 Original line number Original line Diff line number Diff line Loading @@ -464,10 +464,7 @@ const ClipBase* ClipArea::serializeIntersectedClip(LinearAllocator& allocator, } } case ClipMode::Region: case ClipMode::Region: other = getRegion(recordedClip); other = getRegion(recordedClip); applyTransformToRegion(recordedClipTransform, &other); // TODO: handle non-translate transforms properly! other.translate(recordedClipTransform.getTranslateX(), recordedClipTransform.getTranslateY()); } } ClipRegion* regionClip = allocator.create<ClipRegion>(); ClipRegion* regionClip = allocator.create<ClipRegion>(); Loading Loading @@ -527,11 +524,29 @@ void ClipArea::applyClip(const ClipBase* clip, const Matrix4& transform) { } } } else { } else { SkRegion region(getRegion(clip)); SkRegion region(getRegion(clip)); // TODO: handle non-translate transforms properly! applyTransformToRegion(transform, ®ion); region.translate(transform.getTranslateX(), transform.getTranslateY()); clipRegion(region, SkRegion::kIntersect_Op); 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 uirenderer */ } /* namespace android */ } /* namespace android */ libs/hwui/ClipArea.h +2 −0 Original line number Original line Diff line number Diff line Loading @@ -179,6 +179,8 @@ public: const ClipBase* recordedClip, const Matrix4& recordedClipTransform); const ClipBase* recordedClip, const Matrix4& recordedClipTransform); void applyClip(const ClipBase* recordedClip, const Matrix4& recordedClipTransform); void applyClip(const ClipBase* recordedClip, const Matrix4& recordedClipTransform); static void applyTransformToRegion(const Matrix4& transform, SkRegion* region); private: private: void enterRectangleMode(); void enterRectangleMode(); void rectangleModeClipRectWithTransform(const Rect& r, const mat4* transform, SkRegion::Op op); void rectangleModeClipRectWithTransform(const Rect& r, const mat4* transform, SkRegion::Op op); Loading libs/hwui/Rect.h +7 −0 Original line number Original line Diff line number Diff line Loading @@ -73,6 +73,13 @@ public: bottom(height) { bottom(height) { } } inline Rect(const SkIRect& rect): left(rect.fLeft), top(rect.fTop), right(rect.fRight), bottom(rect.fBottom) { } inline Rect(const SkRect& rect): inline Rect(const SkRect& rect): left(rect.fLeft), left(rect.fLeft), top(rect.fTop), top(rect.fTop), Loading libs/hwui/tests/unit/ClipAreaTests.cpp +59 −0 Original line number Original line Diff line number Diff line Loading @@ -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 uirenderer } // namespace android } // namespace android Loading
libs/hwui/ClipArea.cpp +21 −6 Original line number Original line Diff line number Diff line Loading @@ -464,10 +464,7 @@ const ClipBase* ClipArea::serializeIntersectedClip(LinearAllocator& allocator, } } case ClipMode::Region: case ClipMode::Region: other = getRegion(recordedClip); other = getRegion(recordedClip); applyTransformToRegion(recordedClipTransform, &other); // TODO: handle non-translate transforms properly! other.translate(recordedClipTransform.getTranslateX(), recordedClipTransform.getTranslateY()); } } ClipRegion* regionClip = allocator.create<ClipRegion>(); ClipRegion* regionClip = allocator.create<ClipRegion>(); Loading Loading @@ -527,11 +524,29 @@ void ClipArea::applyClip(const ClipBase* clip, const Matrix4& transform) { } } } else { } else { SkRegion region(getRegion(clip)); SkRegion region(getRegion(clip)); // TODO: handle non-translate transforms properly! applyTransformToRegion(transform, ®ion); region.translate(transform.getTranslateX(), transform.getTranslateY()); clipRegion(region, SkRegion::kIntersect_Op); 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 uirenderer */ } /* namespace android */ } /* namespace android */
libs/hwui/ClipArea.h +2 −0 Original line number Original line Diff line number Diff line Loading @@ -179,6 +179,8 @@ public: const ClipBase* recordedClip, const Matrix4& recordedClipTransform); const ClipBase* recordedClip, const Matrix4& recordedClipTransform); void applyClip(const ClipBase* recordedClip, const Matrix4& recordedClipTransform); void applyClip(const ClipBase* recordedClip, const Matrix4& recordedClipTransform); static void applyTransformToRegion(const Matrix4& transform, SkRegion* region); private: private: void enterRectangleMode(); void enterRectangleMode(); void rectangleModeClipRectWithTransform(const Rect& r, const mat4* transform, SkRegion::Op op); void rectangleModeClipRectWithTransform(const Rect& r, const mat4* transform, SkRegion::Op op); Loading
libs/hwui/Rect.h +7 −0 Original line number Original line Diff line number Diff line Loading @@ -73,6 +73,13 @@ public: bottom(height) { bottom(height) { } } inline Rect(const SkIRect& rect): left(rect.fLeft), top(rect.fTop), right(rect.fRight), bottom(rect.fBottom) { } inline Rect(const SkRect& rect): inline Rect(const SkRect& rect): left(rect.fLeft), left(rect.fLeft), top(rect.fTop), top(rect.fTop), Loading
libs/hwui/tests/unit/ClipAreaTests.cpp +59 −0 Original line number Original line Diff line number Diff line Loading @@ -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 uirenderer } // namespace android } // namespace android