blob: 4c03811b0c9604ad5b3d8c1fd76c021578129006 [file] [log] [blame]
Chris Craik95571062015-09-02 12:55:52 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "CanvasState.h"
18
19#include "Matrix.h"
20#include "Rect.h"
sergeyvdccca442016-03-21 15:38:21 -070021#include "hwui/Canvas.h"
Chris Craik95571062015-09-02 12:55:52 -070022#include "utils/LinearAllocator.h"
23
Mike Reed6e49c9f2016-12-02 15:36:59 -050024#include <SkClipOp.h>
John Reck1bcacfd2017-11-03 10:12:19 -070025#include <SkPath.h>
26#include <gtest/gtest.h>
Chris Craik95571062015-09-02 12:55:52 -070027
28namespace android {
29namespace uirenderer {
30
John Reck1bcacfd2017-11-03 10:12:19 -070031class NullClient : public CanvasStateClient {
Chris Craik95571062015-09-02 12:55:52 -070032 void onViewportInitialized() override {}
33 void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {}
34 GLuint getTargetFbo() const override { return 0; }
35};
36
37static NullClient sNullClient;
38
39static bool approxEqual(const Matrix4& a, const Matrix4& b) {
40 for (int i = 0; i < 16; i++) {
41 if (!MathUtils::areEqual(a[i], b[i])) {
42 return false;
43 }
44 }
45 return true;
46}
47
48TEST(CanvasState, gettersAndSetters) {
49 CanvasState state(sNullClient);
John Reck1bcacfd2017-11-03 10:12:19 -070050 state.initializeSaveStack(200, 200, 0, 0, 200, 200, Vector3());
Chris Craik95571062015-09-02 12:55:52 -070051
52 ASSERT_EQ(state.getWidth(), 200);
53 ASSERT_EQ(state.getHeight(), 200);
54
55 Matrix4 simpleTranslate;
56 simpleTranslate.loadTranslate(10, 20, 0);
57 state.setMatrix(simpleTranslate);
58
Chris Craik5430ab22015-12-10 16:28:16 -080059 ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(200, 200));
Chris Craik95571062015-09-02 12:55:52 -070060 ASSERT_EQ(state.getLocalClipBounds(), Rect(-10, -20, 190, 180));
61 EXPECT_TRUE(approxEqual(*state.currentTransform(), simpleTranslate));
62 EXPECT_TRUE(state.clipIsSimple());
63}
64
65TEST(CanvasState, simpleClipping) {
66 CanvasState state(sNullClient);
John Reck1bcacfd2017-11-03 10:12:19 -070067 state.initializeSaveStack(200, 200, 0, 0, 200, 200, Vector3());
Chris Craik95571062015-09-02 12:55:52 -070068
Mike Reed6c67f1d2016-12-14 10:29:54 -050069 state.clipRect(0, 0, 100, 100, SkClipOp::kIntersect);
Chris Craik5430ab22015-12-10 16:28:16 -080070 ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(100, 100));
Chris Craik95571062015-09-02 12:55:52 -070071
Mike Reed6c67f1d2016-12-14 10:29:54 -050072 state.clipRect(10, 10, 200, 200, SkClipOp::kIntersect);
Chris Craik95571062015-09-02 12:55:52 -070073 ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(10, 10, 100, 100));
74
Mike Reeda0a74d52017-03-13 13:26:00 -040075 state.clipRect(50, 50, 150, 150, SkClipOp::kReplace_deprecated);
Chris Craik95571062015-09-02 12:55:52 -070076 ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(50, 50, 150, 150));
77}
78
79TEST(CanvasState, complexClipping) {
80 CanvasState state(sNullClient);
John Reck1bcacfd2017-11-03 10:12:19 -070081 state.initializeSaveStack(200, 200, 0, 0, 200, 200, Vector3());
Chris Craik95571062015-09-02 12:55:52 -070082
Florin Malitaeecff562015-12-21 10:43:01 -050083 state.save(SaveFlags::MatrixClip);
Chris Craik95571062015-09-02 12:55:52 -070084 {
85 // rotated clip causes complex clip
86 state.rotate(10);
87 EXPECT_TRUE(state.clipIsSimple());
Mike Reed6c67f1d2016-12-14 10:29:54 -050088 state.clipRect(0, 0, 200, 200, SkClipOp::kIntersect);
Chris Craik95571062015-09-02 12:55:52 -070089 EXPECT_FALSE(state.clipIsSimple());
90 }
91 state.restore();
92
Florin Malitaeecff562015-12-21 10:43:01 -050093 state.save(SaveFlags::MatrixClip);
Chris Craik95571062015-09-02 12:55:52 -070094 {
95 // subtracted clip causes complex clip
96 EXPECT_TRUE(state.clipIsSimple());
Mike Reed6c67f1d2016-12-14 10:29:54 -050097 state.clipRect(50, 50, 150, 150, SkClipOp::kDifference);
Chris Craik95571062015-09-02 12:55:52 -070098 EXPECT_FALSE(state.clipIsSimple());
99 }
100 state.restore();
101
Florin Malitaeecff562015-12-21 10:43:01 -0500102 state.save(SaveFlags::MatrixClip);
Chris Craik95571062015-09-02 12:55:52 -0700103 {
104 // complex path causes complex clip
105 SkPath path;
106 path.addOval(SkRect::MakeWH(200, 200));
107 EXPECT_TRUE(state.clipIsSimple());
Mike Reed6c67f1d2016-12-14 10:29:54 -0500108 state.clipPath(&path, SkClipOp::kDifference);
Chris Craik95571062015-09-02 12:55:52 -0700109 EXPECT_FALSE(state.clipIsSimple());
110 }
111 state.restore();
112}
113
114TEST(CanvasState, saveAndRestore) {
115 CanvasState state(sNullClient);
John Reck1bcacfd2017-11-03 10:12:19 -0700116 state.initializeSaveStack(200, 200, 0, 0, 200, 200, Vector3());
Chris Craik95571062015-09-02 12:55:52 -0700117
Florin Malitaeecff562015-12-21 10:43:01 -0500118 state.save(SaveFlags::Clip);
Chris Craik95571062015-09-02 12:55:52 -0700119 {
Mike Reed6c67f1d2016-12-14 10:29:54 -0500120 state.clipRect(0, 0, 10, 10, SkClipOp::kIntersect);
Chris Craik5430ab22015-12-10 16:28:16 -0800121 ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(10, 10));
Chris Craik95571062015-09-02 12:55:52 -0700122 }
123 state.restore();
John Reck1bcacfd2017-11-03 10:12:19 -0700124 ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(200, 200)); // verify restore
Chris Craik95571062015-09-02 12:55:52 -0700125
126 Matrix4 simpleTranslate;
127 simpleTranslate.loadTranslate(10, 10, 0);
Florin Malitaeecff562015-12-21 10:43:01 -0500128 state.save(SaveFlags::Matrix);
Chris Craik95571062015-09-02 12:55:52 -0700129 {
130 state.translate(10, 10, 0);
131 EXPECT_TRUE(approxEqual(*state.currentTransform(), simpleTranslate));
132 }
133 state.restore();
134 EXPECT_FALSE(approxEqual(*state.currentTransform(), simpleTranslate));
135}
136
137TEST(CanvasState, saveAndRestoreButNotTooMuch) {
138 CanvasState state(sNullClient);
John Reck1bcacfd2017-11-03 10:12:19 -0700139 state.initializeSaveStack(200, 200, 0, 0, 200, 200, Vector3());
Chris Craik95571062015-09-02 12:55:52 -0700140
John Reck1bcacfd2017-11-03 10:12:19 -0700141 state.save(SaveFlags::Matrix); // NOTE: clip not saved
Chris Craik95571062015-09-02 12:55:52 -0700142 {
Mike Reed6c67f1d2016-12-14 10:29:54 -0500143 state.clipRect(0, 0, 10, 10, SkClipOp::kIntersect);
Chris Craik5430ab22015-12-10 16:28:16 -0800144 ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(10, 10));
Chris Craik95571062015-09-02 12:55:52 -0700145 }
146 state.restore();
John Reck1bcacfd2017-11-03 10:12:19 -0700147 ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(10, 10)); // verify not restored
Chris Craik95571062015-09-02 12:55:52 -0700148
149 Matrix4 simpleTranslate;
150 simpleTranslate.loadTranslate(10, 10, 0);
John Reck1bcacfd2017-11-03 10:12:19 -0700151 state.save(SaveFlags::Clip); // NOTE: matrix not saved
Chris Craik95571062015-09-02 12:55:52 -0700152 {
153 state.translate(10, 10, 0);
154 EXPECT_TRUE(approxEqual(*state.currentTransform(), simpleTranslate));
155 }
156 state.restore();
John Reck1bcacfd2017-11-03 10:12:19 -0700157 EXPECT_TRUE(approxEqual(*state.currentTransform(), simpleTranslate)); // verify not restored
Chris Craik95571062015-09-02 12:55:52 -0700158}
Chris Craik95571062015-09-02 12:55:52 -0700159}
160}