/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "CanvasState.h"

#include "Matrix.h"
#include "Rect.h"
#include "utils/LinearAllocator.h"

#include <gtest/gtest.h>
#include <SkPath.h>
#include <SkRegion.h>
#include <SkCanvas.h>

namespace android {
namespace uirenderer {

class NullClient: public CanvasStateClient {
    void onViewportInitialized() override {}
    void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {}
    GLuint getTargetFbo() const override { return 0; }
};

static NullClient sNullClient;

static bool approxEqual(const Matrix4& a, const Matrix4& b) {
    for (int i = 0; i < 16; i++) {
        if (!MathUtils::areEqual(a[i], b[i])) {
            return false;
        }
    }
    return true;
}

TEST(CanvasState, gettersAndSetters) {
    CanvasState state(sNullClient);
    state.initializeSaveStack(200, 200,
            0, 0, 200, 200, Vector3());

    ASSERT_EQ(state.getWidth(), 200);
    ASSERT_EQ(state.getHeight(), 200);

    Matrix4 simpleTranslate;
    simpleTranslate.loadTranslate(10, 20, 0);
    state.setMatrix(simpleTranslate);

    ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(0, 0, 200, 200));
    ASSERT_EQ(state.getLocalClipBounds(), Rect(-10, -20, 190, 180));
    EXPECT_TRUE(approxEqual(*state.currentTransform(), simpleTranslate));
    EXPECT_TRUE(state.clipIsSimple());
}

TEST(CanvasState, simpleClipping) {
    CanvasState state(sNullClient);
    state.initializeSaveStack(200, 200,
            0, 0, 200, 200, Vector3());

    state.clipRect(0, 0, 100, 100, SkRegion::kIntersect_Op);
    ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(0, 0, 100, 100));

    state.clipRect(10, 10, 200, 200, SkRegion::kIntersect_Op);
    ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(10, 10, 100, 100));

    state.clipRect(50, 50, 150, 150, SkRegion::kReplace_Op);
    ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(50, 50, 150, 150));
}

TEST(CanvasState, complexClipping) {
    CanvasState state(sNullClient);
    state.initializeSaveStack(200, 200,
            0, 0, 200, 200, Vector3());

    state.save(SkCanvas::kClip_SaveFlag | SkCanvas::kMatrix_SaveFlag);
    {
        // rotated clip causes complex clip
        state.rotate(10);
        EXPECT_TRUE(state.clipIsSimple());
        state.clipRect(0, 0, 200, 200, SkRegion::kIntersect_Op);
        EXPECT_FALSE(state.clipIsSimple());
    }
    state.restore();

    state.save(SkCanvas::kClip_SaveFlag | SkCanvas::kMatrix_SaveFlag);
    {
        // subtracted clip causes complex clip
        EXPECT_TRUE(state.clipIsSimple());
        state.clipRect(50, 50, 150, 150, SkRegion::kDifference_Op);
        EXPECT_FALSE(state.clipIsSimple());
    }
    state.restore();

    state.save(SkCanvas::kClip_SaveFlag | SkCanvas::kMatrix_SaveFlag);
    {
        // complex path causes complex clip
        SkPath path;
        path.addOval(SkRect::MakeWH(200, 200));
        EXPECT_TRUE(state.clipIsSimple());
        state.clipPath(&path, SkRegion::kDifference_Op);
        EXPECT_FALSE(state.clipIsSimple());
    }
    state.restore();
}

TEST(CanvasState, saveAndRestore) {
    CanvasState state(sNullClient);
    state.initializeSaveStack(200, 200,
            0, 0, 200, 200, Vector3());

    state.save(SkCanvas::kClip_SaveFlag);
    {
        state.clipRect(0, 0, 10, 10, SkRegion::kIntersect_Op);
        ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(0, 0, 10, 10));
    }
    state.restore();
    ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(0, 0, 200, 200)); // verify restore

    Matrix4 simpleTranslate;
    simpleTranslate.loadTranslate(10, 10, 0);
    state.save(SkCanvas::kMatrix_SaveFlag);
    {
        state.translate(10, 10, 0);
        EXPECT_TRUE(approxEqual(*state.currentTransform(), simpleTranslate));
    }
    state.restore();
    EXPECT_FALSE(approxEqual(*state.currentTransform(), simpleTranslate));
}

TEST(CanvasState, saveAndRestoreButNotTooMuch) {
    CanvasState state(sNullClient);
    state.initializeSaveStack(200, 200,
            0, 0, 200, 200, Vector3());

    state.save(SkCanvas::kMatrix_SaveFlag); // NOTE: clip not saved
    {
        state.clipRect(0, 0, 10, 10, SkRegion::kIntersect_Op);
        ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(0, 0, 10, 10));
    }
    state.restore();
    ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(0, 0, 10, 10)); // verify not restored

    Matrix4 simpleTranslate;
    simpleTranslate.loadTranslate(10, 10, 0);
    state.save(SkCanvas::kClip_SaveFlag); // NOTE: matrix not saved
    {
        state.translate(10, 10, 0);
        EXPECT_TRUE(approxEqual(*state.currentTransform(), simpleTranslate));
    }
    state.restore();
    EXPECT_TRUE(approxEqual(*state.currentTransform(), simpleTranslate)); // verify not restored
}

}
}
