1487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk/*
2487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * Copyright (C) 2015 The Android Open Source Project
3487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk *
4487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * Licensed under the Apache License, Version 2.0 (the "License");
5487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * you may not use this file except in compliance with the License.
6487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * You may obtain a copy of the License at
7487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk *
8487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk *      http://www.apache.org/licenses/LICENSE-2.0
9487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk *
10487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * Unless required by applicable law or agreed to in writing, software
11487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * distributed under the License is distributed on an "AS IS" BASIS,
12487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * See the License for the specific language governing permissions and
14487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * limitations under the License.
15487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk */
16487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
17487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk#include <gtest/gtest.h>
18487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk#include <SkPath.h>
19487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk#include <SkRegion.h>
20487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
21487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk#include "ClipArea.h"
22487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
23487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk#include "Matrix.h"
24487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk#include "Rect.h"
25487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk#include "utils/LinearAllocator.h"
26487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
27487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuknamespace android {
28487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuknamespace uirenderer {
29487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
3069aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craikstatic Rect kViewportBounds(2048, 2048);
31487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
32487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukstatic ClipArea createClipArea() {
33487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    ClipArea area;
34487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    area.setViewportDimensions(kViewportBounds.getWidth(), kViewportBounds.getHeight());
35487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    return area;
36487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk}
37487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
38487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob TsukTEST(TransformedRectangle, basics) {
39487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    Rect r(0, 0, 100, 100);
40487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    Matrix4 minus90;
41487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    minus90.loadRotate(-90);
42487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    minus90.mapRect(r);
43487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    Rect r2(20, 40, 120, 60);
44487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
45487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    Matrix4 m90;
46487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    m90.loadRotate(90);
47487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    TransformedRectangle tr(r, m90);
48487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    EXPECT_TRUE(tr.canSimplyIntersectWith(tr));
49487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
50487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    Matrix4 m0;
51487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    TransformedRectangle tr0(r2, m0);
52487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    EXPECT_FALSE(tr.canSimplyIntersectWith(tr0));
53487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
54487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    Matrix4 m45;
55487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    m45.loadRotate(45);
56487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    TransformedRectangle tr2(r, m45);
57487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    EXPECT_FALSE(tr2.canSimplyIntersectWith(tr));
58487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk}
59487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
60487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob TsukTEST(RectangleList, basics) {
61487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    RectangleList list;
62487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    EXPECT_TRUE(list.isEmpty());
63487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
64487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    Rect r(0, 0, 100, 100);
65487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    Matrix4 m45;
66487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    m45.loadRotate(45);
67487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    list.set(r, m45);
68487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    EXPECT_FALSE(list.isEmpty());
69487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
70487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    Rect r2(20, 20, 200, 200);
71487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    list.intersectWith(r2, m45);
72487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    EXPECT_FALSE(list.isEmpty());
73487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    EXPECT_EQ(1, list.getTransformedRectanglesCount());
74487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
75487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    Rect r3(20, 20, 200, 200);
76487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    Matrix4 m30;
77487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    m30.loadRotate(30);
78487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    list.intersectWith(r2, m30);
79487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    EXPECT_FALSE(list.isEmpty());
80487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    EXPECT_EQ(2, list.getTransformedRectanglesCount());
81487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
82487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    SkRegion clip;
83487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    clip.setRect(0, 0, 2000, 2000);
84487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    SkRegion rgn(list.convertToRegion(clip));
85487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    EXPECT_FALSE(rgn.isEmpty());
86487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk}
87487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
88487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob TsukTEST(ClipArea, basics) {
89487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    ClipArea area(createClipArea());
90487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    EXPECT_FALSE(area.isEmpty());
91487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk}
92487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
93487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob TsukTEST(ClipArea, paths) {
94487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    ClipArea area(createClipArea());
95487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    SkPath path;
96487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    SkScalar r = 100;
97487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    path.addCircle(r, r, r);
98386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik    area.clipPathWithTransform(path, &Matrix4::identity(), SkRegion::kIntersect_Op);
99487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    EXPECT_FALSE(area.isEmpty());
100487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    EXPECT_FALSE(area.isSimple());
101487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    EXPECT_FALSE(area.isRectangleList());
102b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
103487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    Rect clipRect(area.getClipRect());
104487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    Rect expected(0, 0, r * 2, r * 2);
105487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    EXPECT_EQ(expected, clipRect);
106487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    SkRegion clipRegion(area.getClipRegion());
107487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    auto skRect(clipRegion.getBounds());
108487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    Rect regionBounds;
109487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    regionBounds.set(skRect);
110487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    EXPECT_EQ(expected, regionBounds);
111487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk}
1128ce8f3f4d68a7750bc02b5254ebbd8658281e675Chris Craik
1138ce8f3f4d68a7750bc02b5254ebbd8658281e675Chris CraikTEST(ClipArea, replaceNegative) {
1148ce8f3f4d68a7750bc02b5254ebbd8658281e675Chris Craik    ClipArea area(createClipArea());
1158ce8f3f4d68a7750bc02b5254ebbd8658281e675Chris Craik    area.setClip(0, 0, 100, 100);
1168ce8f3f4d68a7750bc02b5254ebbd8658281e675Chris Craik
1178ce8f3f4d68a7750bc02b5254ebbd8658281e675Chris Craik    Rect expected(-50, -50, 50, 50);
118386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik    area.clipRectWithTransform(expected, &Matrix4::identity(), SkRegion::kReplace_Op);
1198ce8f3f4d68a7750bc02b5254ebbd8658281e675Chris Craik    EXPECT_EQ(expected, area.getClipRect());
1208ce8f3f4d68a7750bc02b5254ebbd8658281e675Chris Craik}
121386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik
122e4db79de127cfe961195f52907af8451026eaa20Chris CraikTEST(ClipArea, serializeClip) {
123e4db79de127cfe961195f52907af8451026eaa20Chris Craik    ClipArea area(createClipArea());
124e4db79de127cfe961195f52907af8451026eaa20Chris Craik    LinearAllocator allocator;
125e4db79de127cfe961195f52907af8451026eaa20Chris Craik
126e4db79de127cfe961195f52907af8451026eaa20Chris Craik    // unset clip
127e4db79de127cfe961195f52907af8451026eaa20Chris Craik    EXPECT_EQ(nullptr, area.serializeClip(allocator));
128e4db79de127cfe961195f52907af8451026eaa20Chris Craik
129e4db79de127cfe961195f52907af8451026eaa20Chris Craik    // rect clip
130e4db79de127cfe961195f52907af8451026eaa20Chris Craik    area.setClip(0, 0, 200, 200);
131e4db79de127cfe961195f52907af8451026eaa20Chris Craik    {
132e4db79de127cfe961195f52907af8451026eaa20Chris Craik        auto serializedClip = area.serializeClip(allocator);
133e4db79de127cfe961195f52907af8451026eaa20Chris Craik        ASSERT_NE(nullptr, serializedClip);
134e4db79de127cfe961195f52907af8451026eaa20Chris Craik        ASSERT_EQ(ClipMode::Rectangle, serializedClip->mode);
135bf27b995ae1bc36ee0b24effcaf41ec477e7fae3Chris Craik        ASSERT_FALSE(serializedClip->intersectWithRoot) << "No replace, so no intersectWithRoot";
13604d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik        EXPECT_EQ(Rect(200, 200), serializedClip->rect);
137e4db79de127cfe961195f52907af8451026eaa20Chris Craik        EXPECT_EQ(serializedClip, area.serializeClip(allocator))
138e4db79de127cfe961195f52907af8451026eaa20Chris Craik                << "Requery of clip on unmodified ClipArea must return same pointer.";
139e4db79de127cfe961195f52907af8451026eaa20Chris Craik    }
140e4db79de127cfe961195f52907af8451026eaa20Chris Craik
141e4db79de127cfe961195f52907af8451026eaa20Chris Craik    // rect list
142e4db79de127cfe961195f52907af8451026eaa20Chris Craik    Matrix4 rotate;
14369aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craik    rotate.loadRotate(5.0f);
14469aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craik    area.clipRectWithTransform(Rect(50, 50, 150, 150), &rotate, SkRegion::kIntersect_Op);
145e4db79de127cfe961195f52907af8451026eaa20Chris Craik    {
146e4db79de127cfe961195f52907af8451026eaa20Chris Craik        auto serializedClip = area.serializeClip(allocator);
147e4db79de127cfe961195f52907af8451026eaa20Chris Craik        ASSERT_NE(nullptr, serializedClip);
148e4db79de127cfe961195f52907af8451026eaa20Chris Craik        ASSERT_EQ(ClipMode::RectangleList, serializedClip->mode);
149bf27b995ae1bc36ee0b24effcaf41ec477e7fae3Chris Craik        ASSERT_FALSE(serializedClip->intersectWithRoot) << "No replace, so no intersectWithRoot";
150e4db79de127cfe961195f52907af8451026eaa20Chris Craik        auto clipRectList = reinterpret_cast<const ClipRectList*>(serializedClip);
151b4f4f3e16d8fbb2905dfc168383213161e988f83Chris Craik        EXPECT_EQ(2, clipRectList->rectList.getTransformedRectanglesCount());
15269aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craik        EXPECT_EQ(Rect(37, 54, 145, 163), clipRectList->rect);
153e4db79de127cfe961195f52907af8451026eaa20Chris Craik        EXPECT_EQ(serializedClip, area.serializeClip(allocator))
154e4db79de127cfe961195f52907af8451026eaa20Chris Craik                << "Requery of clip on unmodified ClipArea must return same pointer.";
155e4db79de127cfe961195f52907af8451026eaa20Chris Craik    }
156e4db79de127cfe961195f52907af8451026eaa20Chris Craik
157e4db79de127cfe961195f52907af8451026eaa20Chris Craik    // region
158e4db79de127cfe961195f52907af8451026eaa20Chris Craik    SkPath circlePath;
159e4db79de127cfe961195f52907af8451026eaa20Chris Craik    circlePath.addCircle(100, 100, 100);
160e4db79de127cfe961195f52907af8451026eaa20Chris Craik    area.clipPathWithTransform(circlePath, &Matrix4::identity(), SkRegion::kReplace_Op);
161e4db79de127cfe961195f52907af8451026eaa20Chris Craik    {
162e4db79de127cfe961195f52907af8451026eaa20Chris Craik        auto serializedClip = area.serializeClip(allocator);
163e4db79de127cfe961195f52907af8451026eaa20Chris Craik        ASSERT_NE(nullptr, serializedClip);
164e4db79de127cfe961195f52907af8451026eaa20Chris Craik        ASSERT_EQ(ClipMode::Region, serializedClip->mode);
165bf27b995ae1bc36ee0b24effcaf41ec477e7fae3Chris Craik        ASSERT_TRUE(serializedClip->intersectWithRoot) << "Replace op, so expect intersectWithRoot";
166e4db79de127cfe961195f52907af8451026eaa20Chris Craik        auto clipRegion = reinterpret_cast<const ClipRegion*>(serializedClip);
167b4f4f3e16d8fbb2905dfc168383213161e988f83Chris Craik        EXPECT_EQ(SkIRect::MakeWH(200, 200), clipRegion->region.getBounds())
168e4db79de127cfe961195f52907af8451026eaa20Chris Craik                << "Clip region should be 200x200";
169b4f4f3e16d8fbb2905dfc168383213161e988f83Chris Craik        EXPECT_EQ(Rect(200, 200), clipRegion->rect);
170e4db79de127cfe961195f52907af8451026eaa20Chris Craik        EXPECT_EQ(serializedClip, area.serializeClip(allocator))
171e4db79de127cfe961195f52907af8451026eaa20Chris Craik                << "Requery of clip on unmodified ClipArea must return same pointer.";
172e4db79de127cfe961195f52907af8451026eaa20Chris Craik    }
173487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk}
174e4db79de127cfe961195f52907af8451026eaa20Chris Craik
175bf27b995ae1bc36ee0b24effcaf41ec477e7fae3Chris CraikTEST(ClipArea, serializeClip_pathIntersectWithRoot) {
176bf27b995ae1bc36ee0b24effcaf41ec477e7fae3Chris Craik    ClipArea area(createClipArea());
177bf27b995ae1bc36ee0b24effcaf41ec477e7fae3Chris Craik    LinearAllocator allocator;
178bf27b995ae1bc36ee0b24effcaf41ec477e7fae3Chris Craik    SkPath circlePath;
179bf27b995ae1bc36ee0b24effcaf41ec477e7fae3Chris Craik    circlePath.addCircle(100, 100, 100);
180bf27b995ae1bc36ee0b24effcaf41ec477e7fae3Chris Craik    area.clipPathWithTransform(circlePath, &Matrix4::identity(), SkRegion::kIntersect_Op);
181bf27b995ae1bc36ee0b24effcaf41ec477e7fae3Chris Craik
182bf27b995ae1bc36ee0b24effcaf41ec477e7fae3Chris Craik    auto serializedClip = area.serializeClip(allocator);
183bf27b995ae1bc36ee0b24effcaf41ec477e7fae3Chris Craik    ASSERT_NE(nullptr, serializedClip);
184bf27b995ae1bc36ee0b24effcaf41ec477e7fae3Chris Craik    EXPECT_FALSE(serializedClip->intersectWithRoot) << "No replace, so no intersectWithRoot";
185bf27b995ae1bc36ee0b24effcaf41ec477e7fae3Chris Craik}
186bf27b995ae1bc36ee0b24effcaf41ec477e7fae3Chris Craik
187e4db79de127cfe961195f52907af8451026eaa20Chris CraikTEST(ClipArea, serializeIntersectedClip) {
188e4db79de127cfe961195f52907af8451026eaa20Chris Craik    ClipArea area(createClipArea());
189e4db79de127cfe961195f52907af8451026eaa20Chris Craik    LinearAllocator allocator;
190e4db79de127cfe961195f52907af8451026eaa20Chris Craik
191e4db79de127cfe961195f52907af8451026eaa20Chris Craik    // simple state;
192e4db79de127cfe961195f52907af8451026eaa20Chris Craik    EXPECT_EQ(nullptr, area.serializeIntersectedClip(allocator, nullptr, Matrix4::identity()));
193e4db79de127cfe961195f52907af8451026eaa20Chris Craik    area.setClip(0, 0, 200, 200);
194e4db79de127cfe961195f52907af8451026eaa20Chris Craik    {
195e4db79de127cfe961195f52907af8451026eaa20Chris Craik        auto origRectClip = area.serializeClip(allocator);
196e4db79de127cfe961195f52907af8451026eaa20Chris Craik        ASSERT_NE(nullptr, origRectClip);
197e4db79de127cfe961195f52907af8451026eaa20Chris Craik        EXPECT_EQ(origRectClip, area.serializeIntersectedClip(allocator, nullptr, Matrix4::identity()));
198e4db79de127cfe961195f52907af8451026eaa20Chris Craik    }
199e4db79de127cfe961195f52907af8451026eaa20Chris Craik
200e4db79de127cfe961195f52907af8451026eaa20Chris Craik    // rect
201e4db79de127cfe961195f52907af8451026eaa20Chris Craik    {
202e4db79de127cfe961195f52907af8451026eaa20Chris Craik        ClipRect recordedClip(Rect(100, 100));
203e4db79de127cfe961195f52907af8451026eaa20Chris Craik        Matrix4 translateScale;
204e4db79de127cfe961195f52907af8451026eaa20Chris Craik        translateScale.loadTranslate(100, 100, 0);
205e4db79de127cfe961195f52907af8451026eaa20Chris Craik        translateScale.scale(2, 3, 1);
206e4db79de127cfe961195f52907af8451026eaa20Chris Craik        auto resolvedClip = area.serializeIntersectedClip(allocator, &recordedClip, translateScale);
207e4db79de127cfe961195f52907af8451026eaa20Chris Craik        ASSERT_NE(nullptr, resolvedClip);
208e4db79de127cfe961195f52907af8451026eaa20Chris Craik        ASSERT_EQ(ClipMode::Rectangle, resolvedClip->mode);
20904d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik        EXPECT_EQ(Rect(100, 100, 200, 200), resolvedClip->rect);
210e4db79de127cfe961195f52907af8451026eaa20Chris Craik
211e4db79de127cfe961195f52907af8451026eaa20Chris Craik        EXPECT_EQ(resolvedClip, area.serializeIntersectedClip(allocator, &recordedClip, translateScale))
212e4db79de127cfe961195f52907af8451026eaa20Chris Craik                << "Must return previous serialization, since input is same";
213e4db79de127cfe961195f52907af8451026eaa20Chris Craik
214e4db79de127cfe961195f52907af8451026eaa20Chris Craik        ClipRect recordedClip2(Rect(100, 100));
215e4db79de127cfe961195f52907af8451026eaa20Chris Craik        EXPECT_NE(resolvedClip, area.serializeIntersectedClip(allocator, &recordedClip2, translateScale))
216e4db79de127cfe961195f52907af8451026eaa20Chris Craik                << "Shouldn't return previous serialization, since matrix location is different";
217e4db79de127cfe961195f52907af8451026eaa20Chris Craik    }
218e4db79de127cfe961195f52907af8451026eaa20Chris Craik
219e4db79de127cfe961195f52907af8451026eaa20Chris Craik    // rect list
220e4db79de127cfe961195f52907af8451026eaa20Chris Craik    Matrix4 rotate;
221e4db79de127cfe961195f52907af8451026eaa20Chris Craik    rotate.loadRotate(2.0f);
222e4db79de127cfe961195f52907af8451026eaa20Chris Craik    area.clipRectWithTransform(Rect(200, 200), &rotate, SkRegion::kIntersect_Op);
223e4db79de127cfe961195f52907af8451026eaa20Chris Craik    {
224e4db79de127cfe961195f52907af8451026eaa20Chris Craik        ClipRect recordedClip(Rect(100, 100));
225e4db79de127cfe961195f52907af8451026eaa20Chris Craik        auto resolvedClip = area.serializeIntersectedClip(allocator, &recordedClip, Matrix4::identity());
226e4db79de127cfe961195f52907af8451026eaa20Chris Craik        ASSERT_NE(nullptr, resolvedClip);
227e4db79de127cfe961195f52907af8451026eaa20Chris Craik        ASSERT_EQ(ClipMode::RectangleList, resolvedClip->mode);
228e4db79de127cfe961195f52907af8451026eaa20Chris Craik        auto clipRectList = reinterpret_cast<const ClipRectList*>(resolvedClip);
229e4db79de127cfe961195f52907af8451026eaa20Chris Craik        EXPECT_EQ(2, clipRectList->rectList.getTransformedRectanglesCount());
230e4db79de127cfe961195f52907af8451026eaa20Chris Craik    }
231e4db79de127cfe961195f52907af8451026eaa20Chris Craik
232e4db79de127cfe961195f52907af8451026eaa20Chris Craik    // region
233e4db79de127cfe961195f52907af8451026eaa20Chris Craik    SkPath circlePath;
234e4db79de127cfe961195f52907af8451026eaa20Chris Craik    circlePath.addCircle(100, 100, 100);
235e4db79de127cfe961195f52907af8451026eaa20Chris Craik    area.clipPathWithTransform(circlePath, &Matrix4::identity(), SkRegion::kReplace_Op);
236e4db79de127cfe961195f52907af8451026eaa20Chris Craik    {
237e4db79de127cfe961195f52907af8451026eaa20Chris Craik        SkPath ovalPath;
238e4db79de127cfe961195f52907af8451026eaa20Chris Craik        ovalPath.addOval(SkRect::MakeLTRB(50, 0, 150, 200));
239e4db79de127cfe961195f52907af8451026eaa20Chris Craik
240e4db79de127cfe961195f52907af8451026eaa20Chris Craik        ClipRegion recordedClip;
241e4db79de127cfe961195f52907af8451026eaa20Chris Craik        recordedClip.region.setPath(ovalPath, SkRegion(SkIRect::MakeWH(200, 200)));
242261725fdb2962271c222a049fcdf57bbdc8363c7Chris Craik        recordedClip.rect = Rect(200, 200);
243e4db79de127cfe961195f52907af8451026eaa20Chris Craik
244e4db79de127cfe961195f52907af8451026eaa20Chris Craik        Matrix4 translate10x20;
245e4db79de127cfe961195f52907af8451026eaa20Chris Craik        translate10x20.loadTranslate(10, 20, 0);
246e4db79de127cfe961195f52907af8451026eaa20Chris Craik        auto resolvedClip = area.serializeIntersectedClip(allocator, &recordedClip,
247e4db79de127cfe961195f52907af8451026eaa20Chris Craik                translate10x20); // Note: only translate for now, others not handled correctly
248e4db79de127cfe961195f52907af8451026eaa20Chris Craik        ASSERT_NE(nullptr, resolvedClip);
249e4db79de127cfe961195f52907af8451026eaa20Chris Craik        ASSERT_EQ(ClipMode::Region, resolvedClip->mode);
250e4db79de127cfe961195f52907af8451026eaa20Chris Craik        auto clipRegion = reinterpret_cast<const ClipRegion*>(resolvedClip);
251e4db79de127cfe961195f52907af8451026eaa20Chris Craik        EXPECT_EQ(SkIRect::MakeLTRB(60, 20, 160, 200), clipRegion->region.getBounds());
252e4db79de127cfe961195f52907af8451026eaa20Chris Craik    }
253487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk}
254e4db79de127cfe961195f52907af8451026eaa20Chris Craik
25569aeabe6184bbbe6e731656205ffbef78b7b0f3fChris CraikTEST(ClipArea, serializeIntersectedClip_snap) {
25669aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craik    ClipArea area(createClipArea());
25769aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craik    area.setClip(100.2, 100.4, 500.6, 500.8);
25869aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craik    LinearAllocator allocator;
25969aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craik
26069aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craik    {
26169aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craik        // no recorded clip case
26269aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craik        auto resolvedClip = area.serializeIntersectedClip(allocator, nullptr, Matrix4::identity());
26369aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craik        EXPECT_EQ(Rect(100, 100, 501, 501), resolvedClip->rect);
26469aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craik    }
26569aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craik    {
26669aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craik        // recorded clip case
26769aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craik        ClipRect recordedClip(Rect(100.12, 100.74));
26869aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craik        Matrix4 translateScale;
26969aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craik        translateScale.loadTranslate(100, 100, 0);
27069aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craik        translateScale.scale(2, 3, 1); // recorded clip will have non-int coords, even after transform
27169aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craik        auto resolvedClip = area.serializeIntersectedClip(allocator, &recordedClip, translateScale);
27269aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craik        ASSERT_NE(nullptr, resolvedClip);
27369aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craik        EXPECT_EQ(ClipMode::Rectangle, resolvedClip->mode);
27469aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craik        EXPECT_EQ(Rect(100, 100, 300, 402), resolvedClip->rect);
27569aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craik    }
27669aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craik}
27769aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craik
278e4db79de127cfe961195f52907af8451026eaa20Chris Craik} // namespace uirenderer
279e4db79de127cfe961195f52907af8451026eaa20Chris Craik} // namespace android
280