1 /*
2 * Copyright 2020 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "include/core/SkCanvas.h"
9 #include "include/core/SkStream.h"
10 #include "include/core/SkSurface.h"
11 #include "modules/skottie/include/Skottie.h"
12 #include "tests/Test.h"
13
14 using namespace skottie;
15
DEF_TEST(Skottie_Image_CustomTransform,r)16 DEF_TEST(Skottie_Image_CustomTransform, r) {
17 static constexpr char json[] =
18 R"({
19 "v": "5.2.1",
20 "w": 100,
21 "h": 100,
22 "fr": 10,
23 "ip": 0,
24 "op": 100,
25 "assets": [{
26 "id": "img_0",
27 "p" : "img_0.png",
28 "u" : "images/",
29 "w" : 100,
30 "h" : 50
31 }],
32 "layers": [
33 {
34 "ip": 0,
35 "op": 100,
36 "ty": 2,
37 "refId": "img_0",
38 "ks": {
39 "p": { "a": 0, "k": [0,25] }
40 }
41 }
42 ]
43 })";
44
45 SkMemoryStream stream(json, strlen(json));
46
47 static const struct TestData {
48 float t;
49 SkMatrix m;
50 SkColor c[5]; // expected color samples at center/L/T/R/B
51 } tests[] {
52 { 0, SkMatrix::I(),
53 {0xffff0000, 0xffff0000, 0xff00ff00, 0xffff0000, 0xff00ff00}},
54 { 1, SkMatrix::Translate(50,25) * SkMatrix::Scale(.5f,.5f) * SkMatrix::Translate(-50,-25),
55 {0xffff0000, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00}},
56 { 2, SkMatrix::Translate(-50, 0),
57 {0xff00ff00, 0xffff0000, 0xff00ff00, 0xff00ff00, 0xff00ff00}},
58 { 3, SkMatrix::Translate(0, -25),
59 {0xff00ff00, 0xff00ff00, 0xffff0000, 0xff00ff00, 0xff00ff00}},
60 { 4, SkMatrix::Translate(50, 0),
61 {0xffff0000, 0xff00ff00, 0xff00ff00, 0xffff0000, 0xff00ff00}},
62 { 5, SkMatrix::Translate(0, 25),
63 {0xffff0000, 0xffff0000, 0xff00ff00, 0xffff0000, 0xffff0000}},
64 };
65
66 class TestImageAsset final : public ImageAsset {
67 public:
68 TestImageAsset(const TestData* tst, skiatest::Reporter* r)
69 : fTest(tst)
70 , fReporter(r) {
71 auto surf = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(200, 100));
72 surf->getCanvas()->drawColor(0xffff0000);
73 fImage = surf->makeImageSnapshot();
74 }
75
76 private:
77 bool isMultiFrame() override { return true; }
78
79 FrameData getFrameData(float t) override {
80 REPORTER_ASSERT(fReporter, t == fTest->t);
81
82 return { fImage, SkSamplingOptions(), fTest++->m };
83 }
84
85 sk_sp<SkImage> fImage;
86 const TestData* fTest;
87 skiatest::Reporter* fReporter;
88 };
89
90 class TestResourceProvider final : public ResourceProvider {
91 public:
92 TestResourceProvider(const TestData* tst, skiatest::Reporter* r)
93 : fTest(tst)
94 , fReporter(r) {}
95
96 private:
97 sk_sp<ImageAsset> loadImageAsset(const char[], const char[], const char[]) const override {
98 return sk_make_sp<TestImageAsset>(fTest, fReporter);
99 }
100
101 const TestData* fTest;
102 skiatest::Reporter* fReporter;
103 };
104
105 auto anim = Animation::Builder()
106 .setResourceProvider(sk_make_sp<TestResourceProvider>(tests, r))
107 .make(&stream);
108
109 REPORTER_ASSERT(r, anim);
110
111 static constexpr SkSize render_size{100, 100};
112 auto surf = SkSurfaces::Raster(
113 SkImageInfo::MakeN32Premul(render_size.width(), render_size.height()));
114 auto rect = SkRect::MakeSize(render_size);
115
116 SkPixmap pmap;
117 surf->peekPixels(&pmap);
118
119 for (const auto& tst : tests) {
120 surf->getCanvas()->clear(0xff00ff00);
121 anim->seekFrameTime(tst.t);
122 anim->render(surf->getCanvas(), &rect);
123
124 REPORTER_ASSERT(r,
125 tst.c[0] == pmap.getColor(render_size.width() / 2, render_size.height() / 2));
126 REPORTER_ASSERT(r,
127 tst.c[1] == pmap.getColor(1 , render_size.height() / 2));
128 REPORTER_ASSERT(r,
129 tst.c[2] == pmap.getColor(render_size.width() / 2, 1));
130 REPORTER_ASSERT(r,
131 tst.c[3] == pmap.getColor(render_size.width() - 1, render_size.height() / 2));
132 REPORTER_ASSERT(r,
133 tst.c[4] == pmap.getColor(render_size.width() /2 , render_size.height() - 1));
134 }
135 }
136