19557106c6f84640382a068997b1fc125099d6019Chris Craik/*
29557106c6f84640382a068997b1fc125099d6019Chris Craik * Copyright (C) 2015 The Android Open Source Project
39557106c6f84640382a068997b1fc125099d6019Chris Craik *
49557106c6f84640382a068997b1fc125099d6019Chris Craik * Licensed under the Apache License, Version 2.0 (the "License");
59557106c6f84640382a068997b1fc125099d6019Chris Craik * you may not use this file except in compliance with the License.
69557106c6f84640382a068997b1fc125099d6019Chris Craik * You may obtain a copy of the License at
79557106c6f84640382a068997b1fc125099d6019Chris Craik *
89557106c6f84640382a068997b1fc125099d6019Chris Craik *      http://www.apache.org/licenses/LICENSE-2.0
99557106c6f84640382a068997b1fc125099d6019Chris Craik *
109557106c6f84640382a068997b1fc125099d6019Chris Craik * Unless required by applicable law or agreed to in writing, software
119557106c6f84640382a068997b1fc125099d6019Chris Craik * distributed under the License is distributed on an "AS IS" BASIS,
129557106c6f84640382a068997b1fc125099d6019Chris Craik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139557106c6f84640382a068997b1fc125099d6019Chris Craik * See the License for the specific language governing permissions and
149557106c6f84640382a068997b1fc125099d6019Chris Craik * limitations under the License.
159557106c6f84640382a068997b1fc125099d6019Chris Craik */
169557106c6f84640382a068997b1fc125099d6019Chris Craik
179557106c6f84640382a068997b1fc125099d6019Chris Craik#include "CanvasState.h"
189557106c6f84640382a068997b1fc125099d6019Chris Craik
199557106c6f84640382a068997b1fc125099d6019Chris Craik#include "Matrix.h"
209557106c6f84640382a068997b1fc125099d6019Chris Craik#include "Rect.h"
21dccca44ffda4836b56a21da95a046c9708ffd49csergeyv#include "hwui/Canvas.h"
229557106c6f84640382a068997b1fc125099d6019Chris Craik#include "utils/LinearAllocator.h"
239557106c6f84640382a068997b1fc125099d6019Chris Craik
249557106c6f84640382a068997b1fc125099d6019Chris Craik#include <gtest/gtest.h>
259557106c6f84640382a068997b1fc125099d6019Chris Craik#include <SkPath.h>
266e49c9f007c879f05b035c40c0ba543c00f9d0d0Mike Reed#include <SkClipOp.h>
279557106c6f84640382a068997b1fc125099d6019Chris Craik
289557106c6f84640382a068997b1fc125099d6019Chris Craiknamespace android {
299557106c6f84640382a068997b1fc125099d6019Chris Craiknamespace uirenderer {
309557106c6f84640382a068997b1fc125099d6019Chris Craik
319557106c6f84640382a068997b1fc125099d6019Chris Craikclass NullClient: public CanvasStateClient {
329557106c6f84640382a068997b1fc125099d6019Chris Craik    void onViewportInitialized() override {}
339557106c6f84640382a068997b1fc125099d6019Chris Craik    void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {}
349557106c6f84640382a068997b1fc125099d6019Chris Craik    GLuint getTargetFbo() const override { return 0; }
359557106c6f84640382a068997b1fc125099d6019Chris Craik};
369557106c6f84640382a068997b1fc125099d6019Chris Craik
379557106c6f84640382a068997b1fc125099d6019Chris Craikstatic NullClient sNullClient;
389557106c6f84640382a068997b1fc125099d6019Chris Craik
399557106c6f84640382a068997b1fc125099d6019Chris Craikstatic bool approxEqual(const Matrix4& a, const Matrix4& b) {
409557106c6f84640382a068997b1fc125099d6019Chris Craik    for (int i = 0; i < 16; i++) {
419557106c6f84640382a068997b1fc125099d6019Chris Craik        if (!MathUtils::areEqual(a[i], b[i])) {
429557106c6f84640382a068997b1fc125099d6019Chris Craik            return false;
439557106c6f84640382a068997b1fc125099d6019Chris Craik        }
449557106c6f84640382a068997b1fc125099d6019Chris Craik    }
459557106c6f84640382a068997b1fc125099d6019Chris Craik    return true;
469557106c6f84640382a068997b1fc125099d6019Chris Craik}
479557106c6f84640382a068997b1fc125099d6019Chris Craik
489557106c6f84640382a068997b1fc125099d6019Chris CraikTEST(CanvasState, gettersAndSetters) {
499557106c6f84640382a068997b1fc125099d6019Chris Craik    CanvasState state(sNullClient);
5064e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik    state.initializeSaveStack(200, 200,
5164e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik            0, 0, 200, 200, Vector3());
529557106c6f84640382a068997b1fc125099d6019Chris Craik
539557106c6f84640382a068997b1fc125099d6019Chris Craik    ASSERT_EQ(state.getWidth(), 200);
549557106c6f84640382a068997b1fc125099d6019Chris Craik    ASSERT_EQ(state.getHeight(), 200);
559557106c6f84640382a068997b1fc125099d6019Chris Craik
569557106c6f84640382a068997b1fc125099d6019Chris Craik    Matrix4 simpleTranslate;
579557106c6f84640382a068997b1fc125099d6019Chris Craik    simpleTranslate.loadTranslate(10, 20, 0);
589557106c6f84640382a068997b1fc125099d6019Chris Craik    state.setMatrix(simpleTranslate);
599557106c6f84640382a068997b1fc125099d6019Chris Craik
605430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik    ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(200, 200));
619557106c6f84640382a068997b1fc125099d6019Chris Craik    ASSERT_EQ(state.getLocalClipBounds(), Rect(-10, -20, 190, 180));
629557106c6f84640382a068997b1fc125099d6019Chris Craik    EXPECT_TRUE(approxEqual(*state.currentTransform(), simpleTranslate));
639557106c6f84640382a068997b1fc125099d6019Chris Craik    EXPECT_TRUE(state.clipIsSimple());
649557106c6f84640382a068997b1fc125099d6019Chris Craik}
659557106c6f84640382a068997b1fc125099d6019Chris Craik
669557106c6f84640382a068997b1fc125099d6019Chris CraikTEST(CanvasState, simpleClipping) {
679557106c6f84640382a068997b1fc125099d6019Chris Craik    CanvasState state(sNullClient);
6864e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik    state.initializeSaveStack(200, 200,
6964e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik            0, 0, 200, 200, Vector3());
709557106c6f84640382a068997b1fc125099d6019Chris Craik
716c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed    state.clipRect(0, 0, 100, 100, SkClipOp::kIntersect);
725430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik    ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(100, 100));
739557106c6f84640382a068997b1fc125099d6019Chris Craik
746c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed    state.clipRect(10, 10, 200, 200, SkClipOp::kIntersect);
759557106c6f84640382a068997b1fc125099d6019Chris Craik    ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(10, 10, 100, 100));
769557106c6f84640382a068997b1fc125099d6019Chris Craik
77a0a74d5f8ee1dbd04772ffb1775d045ce6b5934bMike Reed    state.clipRect(50, 50, 150, 150, SkClipOp::kReplace_deprecated);
789557106c6f84640382a068997b1fc125099d6019Chris Craik    ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(50, 50, 150, 150));
799557106c6f84640382a068997b1fc125099d6019Chris Craik}
809557106c6f84640382a068997b1fc125099d6019Chris Craik
819557106c6f84640382a068997b1fc125099d6019Chris CraikTEST(CanvasState, complexClipping) {
829557106c6f84640382a068997b1fc125099d6019Chris Craik    CanvasState state(sNullClient);
8364e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik    state.initializeSaveStack(200, 200,
8464e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik            0, 0, 200, 200, Vector3());
859557106c6f84640382a068997b1fc125099d6019Chris Craik
86eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita    state.save(SaveFlags::MatrixClip);
879557106c6f84640382a068997b1fc125099d6019Chris Craik    {
889557106c6f84640382a068997b1fc125099d6019Chris Craik        // rotated clip causes complex clip
899557106c6f84640382a068997b1fc125099d6019Chris Craik        state.rotate(10);
909557106c6f84640382a068997b1fc125099d6019Chris Craik        EXPECT_TRUE(state.clipIsSimple());
916c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed        state.clipRect(0, 0, 200, 200, SkClipOp::kIntersect);
929557106c6f84640382a068997b1fc125099d6019Chris Craik        EXPECT_FALSE(state.clipIsSimple());
939557106c6f84640382a068997b1fc125099d6019Chris Craik    }
949557106c6f84640382a068997b1fc125099d6019Chris Craik    state.restore();
959557106c6f84640382a068997b1fc125099d6019Chris Craik
96eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita    state.save(SaveFlags::MatrixClip);
979557106c6f84640382a068997b1fc125099d6019Chris Craik    {
989557106c6f84640382a068997b1fc125099d6019Chris Craik        // subtracted clip causes complex clip
999557106c6f84640382a068997b1fc125099d6019Chris Craik        EXPECT_TRUE(state.clipIsSimple());
1006c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed        state.clipRect(50, 50, 150, 150, SkClipOp::kDifference);
1019557106c6f84640382a068997b1fc125099d6019Chris Craik        EXPECT_FALSE(state.clipIsSimple());
1029557106c6f84640382a068997b1fc125099d6019Chris Craik    }
1039557106c6f84640382a068997b1fc125099d6019Chris Craik    state.restore();
1049557106c6f84640382a068997b1fc125099d6019Chris Craik
105eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita    state.save(SaveFlags::MatrixClip);
1069557106c6f84640382a068997b1fc125099d6019Chris Craik    {
1079557106c6f84640382a068997b1fc125099d6019Chris Craik        // complex path causes complex clip
1089557106c6f84640382a068997b1fc125099d6019Chris Craik        SkPath path;
1099557106c6f84640382a068997b1fc125099d6019Chris Craik        path.addOval(SkRect::MakeWH(200, 200));
1109557106c6f84640382a068997b1fc125099d6019Chris Craik        EXPECT_TRUE(state.clipIsSimple());
1116c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed        state.clipPath(&path, SkClipOp::kDifference);
1129557106c6f84640382a068997b1fc125099d6019Chris Craik        EXPECT_FALSE(state.clipIsSimple());
1139557106c6f84640382a068997b1fc125099d6019Chris Craik    }
1149557106c6f84640382a068997b1fc125099d6019Chris Craik    state.restore();
1159557106c6f84640382a068997b1fc125099d6019Chris Craik}
1169557106c6f84640382a068997b1fc125099d6019Chris Craik
1179557106c6f84640382a068997b1fc125099d6019Chris CraikTEST(CanvasState, saveAndRestore) {
1189557106c6f84640382a068997b1fc125099d6019Chris Craik    CanvasState state(sNullClient);
11964e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik    state.initializeSaveStack(200, 200,
12064e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik            0, 0, 200, 200, Vector3());
1219557106c6f84640382a068997b1fc125099d6019Chris Craik
122eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita    state.save(SaveFlags::Clip);
1239557106c6f84640382a068997b1fc125099d6019Chris Craik    {
1246c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed        state.clipRect(0, 0, 10, 10, SkClipOp::kIntersect);
1255430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik        ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(10, 10));
1269557106c6f84640382a068997b1fc125099d6019Chris Craik    }
1279557106c6f84640382a068997b1fc125099d6019Chris Craik    state.restore();
1285430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik    ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(200, 200)); // verify restore
1299557106c6f84640382a068997b1fc125099d6019Chris Craik
1309557106c6f84640382a068997b1fc125099d6019Chris Craik    Matrix4 simpleTranslate;
1319557106c6f84640382a068997b1fc125099d6019Chris Craik    simpleTranslate.loadTranslate(10, 10, 0);
132eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita    state.save(SaveFlags::Matrix);
1339557106c6f84640382a068997b1fc125099d6019Chris Craik    {
1349557106c6f84640382a068997b1fc125099d6019Chris Craik        state.translate(10, 10, 0);
1359557106c6f84640382a068997b1fc125099d6019Chris Craik        EXPECT_TRUE(approxEqual(*state.currentTransform(), simpleTranslate));
1369557106c6f84640382a068997b1fc125099d6019Chris Craik    }
1379557106c6f84640382a068997b1fc125099d6019Chris Craik    state.restore();
1389557106c6f84640382a068997b1fc125099d6019Chris Craik    EXPECT_FALSE(approxEqual(*state.currentTransform(), simpleTranslate));
1399557106c6f84640382a068997b1fc125099d6019Chris Craik}
1409557106c6f84640382a068997b1fc125099d6019Chris Craik
1419557106c6f84640382a068997b1fc125099d6019Chris CraikTEST(CanvasState, saveAndRestoreButNotTooMuch) {
1429557106c6f84640382a068997b1fc125099d6019Chris Craik    CanvasState state(sNullClient);
14364e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik    state.initializeSaveStack(200, 200,
14464e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik            0, 0, 200, 200, Vector3());
1459557106c6f84640382a068997b1fc125099d6019Chris Craik
146eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita    state.save(SaveFlags::Matrix); // NOTE: clip not saved
1479557106c6f84640382a068997b1fc125099d6019Chris Craik    {
1486c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed        state.clipRect(0, 0, 10, 10, SkClipOp::kIntersect);
1495430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik        ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(10, 10));
1509557106c6f84640382a068997b1fc125099d6019Chris Craik    }
1519557106c6f84640382a068997b1fc125099d6019Chris Craik    state.restore();
1525430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik    ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(10, 10)); // verify not restored
1539557106c6f84640382a068997b1fc125099d6019Chris Craik
1549557106c6f84640382a068997b1fc125099d6019Chris Craik    Matrix4 simpleTranslate;
1559557106c6f84640382a068997b1fc125099d6019Chris Craik    simpleTranslate.loadTranslate(10, 10, 0);
156eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita    state.save(SaveFlags::Clip); // NOTE: matrix not saved
1579557106c6f84640382a068997b1fc125099d6019Chris Craik    {
1589557106c6f84640382a068997b1fc125099d6019Chris Craik        state.translate(10, 10, 0);
1599557106c6f84640382a068997b1fc125099d6019Chris Craik        EXPECT_TRUE(approxEqual(*state.currentTransform(), simpleTranslate));
1609557106c6f84640382a068997b1fc125099d6019Chris Craik    }
1619557106c6f84640382a068997b1fc125099d6019Chris Craik    state.restore();
1629557106c6f84640382a068997b1fc125099d6019Chris Craik    EXPECT_TRUE(approxEqual(*state.currentTransform(), simpleTranslate)); // verify not restored
1639557106c6f84640382a068997b1fc125099d6019Chris Craik}
1649557106c6f84640382a068997b1fc125099d6019Chris Craik
1659557106c6f84640382a068997b1fc125099d6019Chris Craik}
1669557106c6f84640382a068997b1fc125099d6019Chris Craik}
167