1 /* 2 * Copyright (C) 2016 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 <VectorDrawable.h> 18 #include <gtest/gtest.h> 19 20 #include <SkClipStack.h> 21 #include <SkLiteRecorder.h> 22 #include <SkSurface_Base.h> 23 #include <string.h> 24 #include "AnimationContext.h" 25 #include "DamageAccumulator.h" 26 #include "FatalTestCanvas.h" 27 #include "IContextFactory.h" 28 #include "SkiaCanvas.h" 29 #include "pipeline/skia/SkiaDisplayList.h" 30 #include "pipeline/skia/SkiaPipeline.h" 31 #include "pipeline/skia/SkiaRecordingCanvas.h" 32 #include "renderthread/CanvasContext.h" 33 #include "tests/common/TestUtils.h" 34 35 using namespace android; 36 using namespace android::uirenderer; 37 using namespace android::uirenderer::renderthread; 38 using namespace android::uirenderer::skiapipeline; 39 40 namespace { 41 42 static void testProperty(std::function<void(RenderProperties&)> propSetupCallback, 43 std::function<void(const SkCanvas&)> opValidateCallback) { 44 static const int CANVAS_WIDTH = 100; 45 static const int CANVAS_HEIGHT = 100; 46 class PropertyTestCanvas : public TestCanvasBase { 47 public: 48 PropertyTestCanvas(std::function<void(const SkCanvas&)> callback) 49 : TestCanvasBase(CANVAS_WIDTH, CANVAS_HEIGHT), mCallback(callback) {} 50 void onDrawRect(const SkRect& rect, const SkPaint& paint) override { 51 EXPECT_EQ(mDrawCounter++, 0); 52 mCallback(*this); 53 } 54 void onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle style) { 55 SkCanvas::onClipRRect(rrect, op, style); 56 } 57 std::function<void(const SkCanvas&)> mCallback; 58 }; 59 60 auto node = TestUtils::createSkiaNode( 61 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, 62 [propSetupCallback](RenderProperties& props, SkiaRecordingCanvas& canvas) { 63 propSetupCallback(props); 64 SkPaint paint; 65 paint.setColor(SK_ColorWHITE); 66 canvas.drawRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, paint); 67 }); 68 69 PropertyTestCanvas canvas(opValidateCallback); 70 RenderNodeDrawable drawable(node.get(), &canvas, true); 71 canvas.drawDrawable(&drawable); 72 EXPECT_EQ(1, canvas.mDrawCounter); 73 } 74 } 75 76 TEST(RenderNodeDrawable, renderPropClipping) { 77 testProperty( 78 [](RenderProperties& properties) { 79 properties.setClipToBounds(true); 80 properties.setClipBounds(android::uirenderer::Rect(10, 20, 300, 400)); 81 }, 82 [](const SkCanvas& canvas) { 83 EXPECT_EQ(SkRect::MakeLTRB(10, 20, 100, 100), TestUtils::getClipBounds(&canvas)) 84 << "Clip rect should be intersection of node bounds and clip bounds"; 85 }); 86 } 87 88 TEST(RenderNodeDrawable, renderPropRevealClip) { 89 testProperty( 90 [](RenderProperties& properties) { 91 properties.mutableRevealClip().set(true, 50, 50, 25); 92 }, 93 [](const SkCanvas& canvas) { 94 EXPECT_EQ(SkRect::MakeLTRB(25, 25, 75, 75), TestUtils::getClipBounds(&canvas)); 95 }); 96 } 97 98 TEST(RenderNodeDrawable, renderPropOutlineClip) { 99 testProperty( 100 [](RenderProperties& properties) { 101 properties.mutableOutline().setShouldClip(true); 102 properties.mutableOutline().setRoundRect(10, 20, 30, 40, 5.0f, 0.5f); 103 }, 104 [](const SkCanvas& canvas) { 105 EXPECT_EQ(SkRect::MakeLTRB(10, 20, 30, 40), TestUtils::getClipBounds(&canvas)); 106 }); 107 } 108 109 TEST(RenderNodeDrawable, renderPropTransform) { 110 testProperty( 111 [](RenderProperties& properties) { 112 properties.setLeftTopRightBottom(10, 10, 110, 110); 113 114 SkMatrix staticMatrix = SkMatrix::MakeScale(1.2f, 1.2f); 115 properties.setStaticMatrix(&staticMatrix); 116 117 // ignored, since static overrides animation 118 SkMatrix animationMatrix = SkMatrix::MakeTrans(15, 15); 119 properties.setAnimationMatrix(&animationMatrix); 120 121 properties.setTranslationX(10); 122 properties.setTranslationY(20); 123 properties.setScaleX(0.5f); 124 properties.setScaleY(0.7f); 125 }, 126 [](const SkCanvas& canvas) { 127 Matrix4 matrix; 128 matrix.loadTranslate(10, 10, 0); // left, top 129 matrix.scale(1.2f, 1.2f, 1); // static matrix 130 // ignore animation matrix, since static overrides it 131 132 // translation xy 133 matrix.translate(10, 20); 134 135 // scale xy (from default pivot - center) 136 matrix.translate(50, 50); 137 matrix.scale(0.5f, 0.7f, 1); 138 matrix.translate(-50, -50); 139 Matrix4 actual(canvas.getTotalMatrix()); 140 EXPECT_MATRIX_APPROX_EQ(matrix, actual) << "Op draw matrix must match expected " 141 "combination of transformation " 142 "properties"; 143 }); 144 } 145