SkiaRenderPropertiesTests.cpp revision 52771272f4f018f4fc6846224bf047497e784af1
152771272f4f018f4fc6846224bf047497e784af1Stan Iliev/* 252771272f4f018f4fc6846224bf047497e784af1Stan Iliev * Copyright (C) 2016 The Android Open Source Project 352771272f4f018f4fc6846224bf047497e784af1Stan Iliev * 452771272f4f018f4fc6846224bf047497e784af1Stan Iliev * Licensed under the Apache License, Version 2.0 (the "License"); 552771272f4f018f4fc6846224bf047497e784af1Stan Iliev * you may not use this file except in compliance with the License. 652771272f4f018f4fc6846224bf047497e784af1Stan Iliev * You may obtain a copy of the License at 752771272f4f018f4fc6846224bf047497e784af1Stan Iliev * 852771272f4f018f4fc6846224bf047497e784af1Stan Iliev * http://www.apache.org/licenses/LICENSE-2.0 952771272f4f018f4fc6846224bf047497e784af1Stan Iliev * 1052771272f4f018f4fc6846224bf047497e784af1Stan Iliev * Unless required by applicable law or agreed to in writing, software 1152771272f4f018f4fc6846224bf047497e784af1Stan Iliev * distributed under the License is distributed on an "AS IS" BASIS, 1252771272f4f018f4fc6846224bf047497e784af1Stan Iliev * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1352771272f4f018f4fc6846224bf047497e784af1Stan Iliev * See the License for the specific language governing permissions and 1452771272f4f018f4fc6846224bf047497e784af1Stan Iliev * limitations under the License. 1552771272f4f018f4fc6846224bf047497e784af1Stan Iliev */ 1652771272f4f018f4fc6846224bf047497e784af1Stan Iliev 1752771272f4f018f4fc6846224bf047497e784af1Stan Iliev#include <gtest/gtest.h> 1852771272f4f018f4fc6846224bf047497e784af1Stan Iliev#include <VectorDrawable.h> 1952771272f4f018f4fc6846224bf047497e784af1Stan Iliev 2052771272f4f018f4fc6846224bf047497e784af1Stan Iliev#include "AnimationContext.h" 2152771272f4f018f4fc6846224bf047497e784af1Stan Iliev#include "DamageAccumulator.h" 2252771272f4f018f4fc6846224bf047497e784af1Stan Iliev#include "IContextFactory.h" 2352771272f4f018f4fc6846224bf047497e784af1Stan Iliev#include "pipeline/skia/SkiaDisplayList.h" 2452771272f4f018f4fc6846224bf047497e784af1Stan Iliev#include "pipeline/skia/SkiaPipeline.h" 2552771272f4f018f4fc6846224bf047497e784af1Stan Iliev#include "pipeline/skia/SkiaRecordingCanvas.h" 2652771272f4f018f4fc6846224bf047497e784af1Stan Iliev#include "renderthread/CanvasContext.h" 2752771272f4f018f4fc6846224bf047497e784af1Stan Iliev#include "tests/common/TestUtils.h" 2852771272f4f018f4fc6846224bf047497e784af1Stan Iliev#include "SkiaCanvas.h" 2952771272f4f018f4fc6846224bf047497e784af1Stan Iliev#include <SkSurface_Base.h> 3052771272f4f018f4fc6846224bf047497e784af1Stan Iliev#include <SkLiteRecorder.h> 3152771272f4f018f4fc6846224bf047497e784af1Stan Iliev#include <SkClipStack.h> 3252771272f4f018f4fc6846224bf047497e784af1Stan Iliev#include "FatalTestCanvas.h" 3352771272f4f018f4fc6846224bf047497e784af1Stan Iliev#include <string.h> 3452771272f4f018f4fc6846224bf047497e784af1Stan Iliev 3552771272f4f018f4fc6846224bf047497e784af1Stan Ilievusing namespace android; 3652771272f4f018f4fc6846224bf047497e784af1Stan Ilievusing namespace android::uirenderer; 3752771272f4f018f4fc6846224bf047497e784af1Stan Ilievusing namespace android::uirenderer::renderthread; 3852771272f4f018f4fc6846224bf047497e784af1Stan Ilievusing namespace android::uirenderer::skiapipeline; 3952771272f4f018f4fc6846224bf047497e784af1Stan Iliev 4052771272f4f018f4fc6846224bf047497e784af1Stan Ilievnamespace { 4152771272f4f018f4fc6846224bf047497e784af1Stan Iliev 4252771272f4f018f4fc6846224bf047497e784af1Stan Ilievstatic void testProperty(std::function<void(RenderProperties&)> propSetupCallback, 4352771272f4f018f4fc6846224bf047497e784af1Stan Iliev std::function<void(const SkCanvas&)> opValidateCallback) { 4452771272f4f018f4fc6846224bf047497e784af1Stan Iliev static const int CANVAS_WIDTH = 100; 4552771272f4f018f4fc6846224bf047497e784af1Stan Iliev static const int CANVAS_HEIGHT = 100; 4652771272f4f018f4fc6846224bf047497e784af1Stan Iliev class PropertyTestCanvas : public TestCanvasBase { 4752771272f4f018f4fc6846224bf047497e784af1Stan Iliev public: 4852771272f4f018f4fc6846224bf047497e784af1Stan Iliev PropertyTestCanvas(std::function<void(const SkCanvas&)> callback) 4952771272f4f018f4fc6846224bf047497e784af1Stan Iliev : TestCanvasBase(CANVAS_WIDTH, CANVAS_HEIGHT), mCallback(callback) {} 5052771272f4f018f4fc6846224bf047497e784af1Stan Iliev void onDrawRect(const SkRect& rect, const SkPaint& paint) override { 5152771272f4f018f4fc6846224bf047497e784af1Stan Iliev EXPECT_EQ(mDrawCounter++, 0); 5252771272f4f018f4fc6846224bf047497e784af1Stan Iliev mCallback(*this); 5352771272f4f018f4fc6846224bf047497e784af1Stan Iliev } 5452771272f4f018f4fc6846224bf047497e784af1Stan Iliev void onClipRRect(const SkRRect& rrect, ClipOp op, ClipEdgeStyle style) { 5552771272f4f018f4fc6846224bf047497e784af1Stan Iliev SkCanvas::onClipRRect(rrect, op, style); 5652771272f4f018f4fc6846224bf047497e784af1Stan Iliev } 5752771272f4f018f4fc6846224bf047497e784af1Stan Iliev std::function<void(const SkCanvas&)> mCallback; 5852771272f4f018f4fc6846224bf047497e784af1Stan Iliev }; 5952771272f4f018f4fc6846224bf047497e784af1Stan Iliev 6052771272f4f018f4fc6846224bf047497e784af1Stan Iliev auto node = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, 6152771272f4f018f4fc6846224bf047497e784af1Stan Iliev [propSetupCallback](RenderProperties& props, SkiaRecordingCanvas& canvas) { 6252771272f4f018f4fc6846224bf047497e784af1Stan Iliev propSetupCallback(props); 6352771272f4f018f4fc6846224bf047497e784af1Stan Iliev SkPaint paint; 6452771272f4f018f4fc6846224bf047497e784af1Stan Iliev paint.setColor(SK_ColorWHITE); 6552771272f4f018f4fc6846224bf047497e784af1Stan Iliev canvas.drawRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, paint); 6652771272f4f018f4fc6846224bf047497e784af1Stan Iliev }); 6752771272f4f018f4fc6846224bf047497e784af1Stan Iliev 6852771272f4f018f4fc6846224bf047497e784af1Stan Iliev sk_sp<PropertyTestCanvas> canvas(new PropertyTestCanvas(opValidateCallback)); 6952771272f4f018f4fc6846224bf047497e784af1Stan Iliev RenderNodeDrawable drawable(node.get(), canvas.get(), true); 7052771272f4f018f4fc6846224bf047497e784af1Stan Iliev canvas->drawDrawable(&drawable); 7152771272f4f018f4fc6846224bf047497e784af1Stan Iliev EXPECT_EQ(1, canvas->mDrawCounter); 7252771272f4f018f4fc6846224bf047497e784af1Stan Iliev} 7352771272f4f018f4fc6846224bf047497e784af1Stan Iliev 7452771272f4f018f4fc6846224bf047497e784af1Stan Iliev} 7552771272f4f018f4fc6846224bf047497e784af1Stan Iliev 7652771272f4f018f4fc6846224bf047497e784af1Stan IlievRENDERTHREAD_TEST(RenderNodeDrawable, renderPropClipping) { 7752771272f4f018f4fc6846224bf047497e784af1Stan Iliev testProperty([](RenderProperties& properties) { 7852771272f4f018f4fc6846224bf047497e784af1Stan Iliev properties.setClipToBounds(true); 7952771272f4f018f4fc6846224bf047497e784af1Stan Iliev properties.setClipBounds(android::uirenderer::Rect(10, 20, 300, 400)); 8052771272f4f018f4fc6846224bf047497e784af1Stan Iliev }, [](const SkCanvas& canvas) { 8152771272f4f018f4fc6846224bf047497e784af1Stan Iliev EXPECT_EQ(SkRect::MakeLTRB(10, 20, 100, 100), TestUtils::getClipBounds(&canvas)) 8252771272f4f018f4fc6846224bf047497e784af1Stan Iliev << "Clip rect should be intersection of node bounds and clip bounds"; 8352771272f4f018f4fc6846224bf047497e784af1Stan Iliev }); 8452771272f4f018f4fc6846224bf047497e784af1Stan Iliev} 8552771272f4f018f4fc6846224bf047497e784af1Stan Iliev 8652771272f4f018f4fc6846224bf047497e784af1Stan IlievRENDERTHREAD_TEST(RenderNodeDrawable, renderPropRevealClip) { 8752771272f4f018f4fc6846224bf047497e784af1Stan Iliev testProperty([](RenderProperties& properties) { 8852771272f4f018f4fc6846224bf047497e784af1Stan Iliev properties.mutableRevealClip().set(true, 50, 50, 25); 8952771272f4f018f4fc6846224bf047497e784af1Stan Iliev }, [](const SkCanvas& canvas) { 9052771272f4f018f4fc6846224bf047497e784af1Stan Iliev SkClipStack::Iter it(*canvas.getClipStack(), SkClipStack::Iter::kBottom_IterStart); 9152771272f4f018f4fc6846224bf047497e784af1Stan Iliev const SkClipStack::Element *top = it.next(); 9252771272f4f018f4fc6846224bf047497e784af1Stan Iliev ASSERT_NE(nullptr, top); 9352771272f4f018f4fc6846224bf047497e784af1Stan Iliev SkPath clip; 9452771272f4f018f4fc6846224bf047497e784af1Stan Iliev top->asPath(&clip); 9552771272f4f018f4fc6846224bf047497e784af1Stan Iliev SkRect rect; 9652771272f4f018f4fc6846224bf047497e784af1Stan Iliev EXPECT_TRUE(clip.isOval(&rect)); 9752771272f4f018f4fc6846224bf047497e784af1Stan Iliev EXPECT_EQ(SkRect::MakeLTRB(25, 25, 75, 75), rect); 9852771272f4f018f4fc6846224bf047497e784af1Stan Iliev }); 9952771272f4f018f4fc6846224bf047497e784af1Stan Iliev} 10052771272f4f018f4fc6846224bf047497e784af1Stan Iliev 10152771272f4f018f4fc6846224bf047497e784af1Stan IlievRENDERTHREAD_TEST(RenderNodeDrawable, renderPropOutlineClip) { 10252771272f4f018f4fc6846224bf047497e784af1Stan Iliev testProperty([](RenderProperties& properties) { 10352771272f4f018f4fc6846224bf047497e784af1Stan Iliev properties.mutableOutline().setShouldClip(true); 10452771272f4f018f4fc6846224bf047497e784af1Stan Iliev properties.mutableOutline().setRoundRect(10, 20, 30, 40, 5.0f, 0.5f); 10552771272f4f018f4fc6846224bf047497e784af1Stan Iliev }, [](const SkCanvas& canvas) { 10652771272f4f018f4fc6846224bf047497e784af1Stan Iliev SkClipStack::Iter it(*canvas.getClipStack(), SkClipStack::Iter::kBottom_IterStart); 10752771272f4f018f4fc6846224bf047497e784af1Stan Iliev const SkClipStack::Element *top = it.next(); 10852771272f4f018f4fc6846224bf047497e784af1Stan Iliev ASSERT_NE(nullptr, top); 10952771272f4f018f4fc6846224bf047497e784af1Stan Iliev SkPath clip; 11052771272f4f018f4fc6846224bf047497e784af1Stan Iliev top->asPath(&clip); 11152771272f4f018f4fc6846224bf047497e784af1Stan Iliev SkRRect rrect; 11252771272f4f018f4fc6846224bf047497e784af1Stan Iliev EXPECT_TRUE(clip.isRRect(&rrect)); 11352771272f4f018f4fc6846224bf047497e784af1Stan Iliev EXPECT_EQ(SkRRect::MakeRectXY(SkRect::MakeLTRB(10, 20, 30, 40), 5.0f, 5.0f), rrect); 11452771272f4f018f4fc6846224bf047497e784af1Stan Iliev }); 11552771272f4f018f4fc6846224bf047497e784af1Stan Iliev} 11652771272f4f018f4fc6846224bf047497e784af1Stan Iliev 11752771272f4f018f4fc6846224bf047497e784af1Stan IlievRENDERTHREAD_TEST(RenderNodeDrawable, renderPropTransform) { 11852771272f4f018f4fc6846224bf047497e784af1Stan Iliev testProperty([](RenderProperties& properties) { 11952771272f4f018f4fc6846224bf047497e784af1Stan Iliev properties.setLeftTopRightBottom(10, 10, 110, 110); 12052771272f4f018f4fc6846224bf047497e784af1Stan Iliev 12152771272f4f018f4fc6846224bf047497e784af1Stan Iliev SkMatrix staticMatrix = SkMatrix::MakeScale(1.2f, 1.2f); 12252771272f4f018f4fc6846224bf047497e784af1Stan Iliev properties.setStaticMatrix(&staticMatrix); 12352771272f4f018f4fc6846224bf047497e784af1Stan Iliev 12452771272f4f018f4fc6846224bf047497e784af1Stan Iliev // ignored, since static overrides animation 12552771272f4f018f4fc6846224bf047497e784af1Stan Iliev SkMatrix animationMatrix = SkMatrix::MakeTrans(15, 15); 12652771272f4f018f4fc6846224bf047497e784af1Stan Iliev properties.setAnimationMatrix(&animationMatrix); 12752771272f4f018f4fc6846224bf047497e784af1Stan Iliev 12852771272f4f018f4fc6846224bf047497e784af1Stan Iliev properties.setTranslationX(10); 12952771272f4f018f4fc6846224bf047497e784af1Stan Iliev properties.setTranslationY(20); 13052771272f4f018f4fc6846224bf047497e784af1Stan Iliev properties.setScaleX(0.5f); 13152771272f4f018f4fc6846224bf047497e784af1Stan Iliev properties.setScaleY(0.7f); 13252771272f4f018f4fc6846224bf047497e784af1Stan Iliev }, [](const SkCanvas& canvas) { 13352771272f4f018f4fc6846224bf047497e784af1Stan Iliev Matrix4 matrix; 13452771272f4f018f4fc6846224bf047497e784af1Stan Iliev matrix.loadTranslate(10, 10, 0); // left, top 13552771272f4f018f4fc6846224bf047497e784af1Stan Iliev matrix.scale(1.2f, 1.2f, 1); // static matrix 13652771272f4f018f4fc6846224bf047497e784af1Stan Iliev // ignore animation matrix, since static overrides it 13752771272f4f018f4fc6846224bf047497e784af1Stan Iliev 13852771272f4f018f4fc6846224bf047497e784af1Stan Iliev // translation xy 13952771272f4f018f4fc6846224bf047497e784af1Stan Iliev matrix.translate(10, 20); 14052771272f4f018f4fc6846224bf047497e784af1Stan Iliev 14152771272f4f018f4fc6846224bf047497e784af1Stan Iliev // scale xy (from default pivot - center) 14252771272f4f018f4fc6846224bf047497e784af1Stan Iliev matrix.translate(50, 50); 14352771272f4f018f4fc6846224bf047497e784af1Stan Iliev matrix.scale(0.5f, 0.7f, 1); 14452771272f4f018f4fc6846224bf047497e784af1Stan Iliev matrix.translate(-50, -50); 14552771272f4f018f4fc6846224bf047497e784af1Stan Iliev Matrix4 actual(canvas.getTotalMatrix()); 14652771272f4f018f4fc6846224bf047497e784af1Stan Iliev EXPECT_MATRIX_APPROX_EQ(matrix, actual) 14752771272f4f018f4fc6846224bf047497e784af1Stan Iliev << "Op draw matrix must match expected combination of transformation properties"; 14852771272f4f018f4fc6846224bf047497e784af1Stan Iliev }); 14952771272f4f018f4fc6846224bf047497e784af1Stan Iliev} 150