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