Home | History | Annotate | Download | only in unit
      1 /*
      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"
     21 #include "hwui/Canvas.h"
     22 #include "utils/LinearAllocator.h"
     23 
     24 #include <gtest/gtest.h>
     25 #include <SkPath.h>
     26 #include <SkRegion.h>
     27 
     28 namespace android {
     29 namespace uirenderer {
     30 
     31 class NullClient: public CanvasStateClient {
     32     void onViewportInitialized() override {}
     33     void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {}
     34     GLuint getTargetFbo() const override { return 0; }
     35 };
     36 
     37 static NullClient sNullClient;
     38 
     39 static 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 
     48 TEST(CanvasState, gettersAndSetters) {
     49     CanvasState state(sNullClient);
     50     state.initializeSaveStack(200, 200,
     51             0, 0, 200, 200, Vector3());
     52 
     53     ASSERT_EQ(state.getWidth(), 200);
     54     ASSERT_EQ(state.getHeight(), 200);
     55 
     56     Matrix4 simpleTranslate;
     57     simpleTranslate.loadTranslate(10, 20, 0);
     58     state.setMatrix(simpleTranslate);
     59 
     60     ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(200, 200));
     61     ASSERT_EQ(state.getLocalClipBounds(), Rect(-10, -20, 190, 180));
     62     EXPECT_TRUE(approxEqual(*state.currentTransform(), simpleTranslate));
     63     EXPECT_TRUE(state.clipIsSimple());
     64 }
     65 
     66 TEST(CanvasState, simpleClipping) {
     67     CanvasState state(sNullClient);
     68     state.initializeSaveStack(200, 200,
     69             0, 0, 200, 200, Vector3());
     70 
     71     state.clipRect(0, 0, 100, 100, SkRegion::kIntersect_Op);
     72     ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(100, 100));
     73 
     74     state.clipRect(10, 10, 200, 200, SkRegion::kIntersect_Op);
     75     ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(10, 10, 100, 100));
     76 
     77     state.clipRect(50, 50, 150, 150, SkRegion::kReplace_Op);
     78     ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(50, 50, 150, 150));
     79 }
     80 
     81 TEST(CanvasState, complexClipping) {
     82     CanvasState state(sNullClient);
     83     state.initializeSaveStack(200, 200,
     84             0, 0, 200, 200, Vector3());
     85 
     86     state.save(SaveFlags::MatrixClip);
     87     {
     88         // rotated clip causes complex clip
     89         state.rotate(10);
     90         EXPECT_TRUE(state.clipIsSimple());
     91         state.clipRect(0, 0, 200, 200, SkRegion::kIntersect_Op);
     92         EXPECT_FALSE(state.clipIsSimple());
     93     }
     94     state.restore();
     95 
     96     state.save(SaveFlags::MatrixClip);
     97     {
     98         // subtracted clip causes complex clip
     99         EXPECT_TRUE(state.clipIsSimple());
    100         state.clipRect(50, 50, 150, 150, SkRegion::kDifference_Op);
    101         EXPECT_FALSE(state.clipIsSimple());
    102     }
    103     state.restore();
    104 
    105     state.save(SaveFlags::MatrixClip);
    106     {
    107         // complex path causes complex clip
    108         SkPath path;
    109         path.addOval(SkRect::MakeWH(200, 200));
    110         EXPECT_TRUE(state.clipIsSimple());
    111         state.clipPath(&path, SkRegion::kDifference_Op);
    112         EXPECT_FALSE(state.clipIsSimple());
    113     }
    114     state.restore();
    115 }
    116 
    117 TEST(CanvasState, saveAndRestore) {
    118     CanvasState state(sNullClient);
    119     state.initializeSaveStack(200, 200,
    120             0, 0, 200, 200, Vector3());
    121 
    122     state.save(SaveFlags::Clip);
    123     {
    124         state.clipRect(0, 0, 10, 10, SkRegion::kIntersect_Op);
    125         ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(10, 10));
    126     }
    127     state.restore();
    128     ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(200, 200)); // verify restore
    129 
    130     Matrix4 simpleTranslate;
    131     simpleTranslate.loadTranslate(10, 10, 0);
    132     state.save(SaveFlags::Matrix);
    133     {
    134         state.translate(10, 10, 0);
    135         EXPECT_TRUE(approxEqual(*state.currentTransform(), simpleTranslate));
    136     }
    137     state.restore();
    138     EXPECT_FALSE(approxEqual(*state.currentTransform(), simpleTranslate));
    139 }
    140 
    141 TEST(CanvasState, saveAndRestoreButNotTooMuch) {
    142     CanvasState state(sNullClient);
    143     state.initializeSaveStack(200, 200,
    144             0, 0, 200, 200, Vector3());
    145 
    146     state.save(SaveFlags::Matrix); // NOTE: clip not saved
    147     {
    148         state.clipRect(0, 0, 10, 10, SkRegion::kIntersect_Op);
    149         ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(10, 10));
    150     }
    151     state.restore();
    152     ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(10, 10)); // verify not restored
    153 
    154     Matrix4 simpleTranslate;
    155     simpleTranslate.loadTranslate(10, 10, 0);
    156     state.save(SaveFlags::Clip); // NOTE: matrix not saved
    157     {
    158         state.translate(10, 10, 0);
    159         EXPECT_TRUE(approxEqual(*state.currentTransform(), simpleTranslate));
    160     }
    161     state.restore();
    162     EXPECT_TRUE(approxEqual(*state.currentTransform(), simpleTranslate)); // verify not restored
    163 }
    164 
    165 }
    166 }
    167