Update rive-cpp to 2.0 version
[platform/core/uifw/rive-tizen.git] / submodule / skia / modules / particles / src / SkParticleBinding.cpp
1 /*
2 * Copyright 2019 Google LLC
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 "modules/particles/include/SkParticleBinding.h"
9
10 #include "include/core/SkColorSpace.h"
11 #include "include/core/SkContourMeasure.h"
12 #include "include/core/SkFont.h"
13 #include "include/core/SkImage.h"
14 #include "include/core/SkPath.h"
15 #include "include/private/SkTPin.h"
16 #include "include/utils/SkParsePath.h"
17 #include "include/utils/SkTextUtils.h"
18 #include "modules/particles/include/SkReflected.h"
19 #include "modules/skresources/include/SkResources.h"
20 #include "src/core/SkMatrixProvider.h"
21 #include "src/core/SkVM.h"
22 #include "src/shaders/SkShaderBase.h"
23 #include "src/sksl/SkSLCompiler.h"
24
25 void SkParticleBinding::visitFields(SkFieldVisitor* v) {
26     v->visit("Name", fName);
27 }
28
29 namespace {
30     struct PosNrm { SkPoint pos; SkVector nrm; };
31     using LinearizedPath = std::vector<PosNrm>;
32 }  // namespace
33
34 static LinearizedPath linearize_path(const SkPath& path) {
35     LinearizedPath lin;
36     SkContourMeasureIter iter(path, false);
37     while (auto contour = iter.next()) {
38         for (SkScalar x = 0; x < contour->length(); x++) {
39             SkPoint pos;
40             SkVector tan;
41             SkAssertResult(contour->getPosTan(x, &pos, &tan));
42             lin.push_back({pos, {tan.fY, -tan.fX}});
43         }
44     }
45     return lin;
46 }
47
48 // Exposes an SkPath as an external, callable function. p(x) returns a float4 { pos.xy, normal.xy }
49 class SkPathExternalFunction : public SkParticleExternalFunction {
50 public:
51     SkPathExternalFunction(const char* name,
52                            SkSL::Compiler& compiler,
53                            const LinearizedPath& path,
54                            skvm::Uniforms* uniforms,
55                            SkArenaAlloc* alloc)
56             : SkParticleExternalFunction(
57                       name, compiler, *compiler.context().fTypes.fFloat4, uniforms, alloc)
58             , fPath(path) {}
59
60     int callParameterCount() const override { return 1; }
61     void getCallParameterTypes(const SkSL::Type** outTypes) const override {
62         outTypes[0] = fCompiler.context().fTypes.fFloat.get();
63     }
64
65     void call(skvm::Builder* builder,
66               skvm::F32* arguments,
67               skvm::F32* outResult,
68               skvm::I32 mask) const override {
69         if (fPath.empty()) {
70             return;
71         }
72
73         skvm::Uniform ptr = fUniforms->pushPtr(fPath.data());
74         skvm::I32 index = trunc(clamp(arguments[0] * fPath.size(), 0, fPath.size() - 1));
75
76         outResult[0] = builder->gatherF(ptr, (index<<2)+0);
77         outResult[1] = builder->gatherF(ptr, (index<<2)+1);
78         outResult[2] = builder->gatherF(ptr, (index<<2)+2);
79         outResult[3] = builder->gatherF(ptr, (index<<2)+3);
80     }
81
82 private:
83     const LinearizedPath& fPath;
84 };
85
86 class SkPathBinding : public SkParticleBinding {
87 public:
88     SkPathBinding(const char* name = "", const char* pathPath = "", const char* pathName = "")
89             : SkParticleBinding(name)
90             , fPathPath(pathPath)
91             , fPathName(pathName) {}
92
93     REFLECTED(SkPathBinding, SkParticleBinding)
94
95     void visitFields(SkFieldVisitor* v) override {
96         SkParticleBinding::visitFields(v);
97         v->visit("PathPath", fPathPath);
98         v->visit("PathName", fPathName);
99     }
100
101     std::unique_ptr<SkParticleExternalFunction> toFunction(SkSL::Compiler& compiler,
102                                                            skvm::Uniforms* uniforms,
103                                                            SkArenaAlloc* alloc) override {
104         return std::make_unique<SkPathExternalFunction>(fName.c_str(), compiler, fData, uniforms,
105                                                         alloc);
106     }
107
108     void prepare(const skresources::ResourceProvider* resourceProvider) override {
109         if (auto pathData = resourceProvider->load(fPathPath.c_str(), fPathName.c_str())) {
110             SkPath path;
111             if (0 != path.readFromMemory(pathData->data(), pathData->size())) {
112                 fData = linearize_path(path);
113             }
114         }
115     }
116
117 private:
118     SkString fPathPath;
119     SkString fPathName;
120
121     // Cached
122     LinearizedPath fData;
123 };
124
125 class SkTextBinding : public SkParticleBinding {
126 public:
127     SkTextBinding(const char* name = "", const char* text = "", SkScalar fontSize = 96)
128             : SkParticleBinding(name)
129             , fText(text)
130             , fFontSize(fontSize) {}
131
132     REFLECTED(SkTextBinding, SkParticleBinding)
133
134     void visitFields(SkFieldVisitor* v) override {
135         SkParticleBinding::visitFields(v);
136         v->visit("Text", fText);
137         v->visit("FontSize", fFontSize);
138     }
139
140     std::unique_ptr<SkParticleExternalFunction> toFunction(SkSL::Compiler& compiler,
141                                                            skvm::Uniforms* uniforms,
142                                                            SkArenaAlloc* alloc) override {
143         return std::make_unique<SkPathExternalFunction>(fName.c_str(), compiler, fData, uniforms,
144                                                         alloc);
145     }
146
147     void prepare(const skresources::ResourceProvider*) override {
148         if (fText.isEmpty()) {
149             return;
150         }
151
152         SkFont font(nullptr, fFontSize);
153         SkPath path;
154         SkTextUtils::GetPath(fText.c_str(), fText.size(), SkTextEncoding::kUTF8, 0, 0, font, &path);
155         fData = linearize_path(path);
156     }
157
158 private:
159     SkString fText;
160     SkScalar fFontSize;
161
162     // Cached
163     LinearizedPath fData;
164 };
165
166 // Exposes an SkShader as an external, callable function. p(xy) returns a float4
167 class SkShaderExternalFunction : public SkParticleExternalFunction {
168 public:
169     SkShaderExternalFunction(const char* name,
170                              SkSL::Compiler& compiler,
171                              sk_sp<SkShader> shader,
172                              skvm::Uniforms* uniforms,
173                              SkArenaAlloc* alloc)
174             : SkParticleExternalFunction(
175                       name, compiler, *compiler.context().fTypes.fFloat4, uniforms, alloc)
176             , fShader(std::move(shader)) {}
177
178     int callParameterCount() const override { return 1; }
179     void getCallParameterTypes(const SkSL::Type** outTypes) const override {
180         outTypes[0] = fCompiler.context().fTypes.fFloat2.get();
181     }
182
183     void call(skvm::Builder* builder,
184               skvm::F32* arguments,
185               skvm::F32* outResult,
186               skvm::I32 mask) const override {
187         skvm::Coord coord = {arguments[0], arguments[1]};
188         skvm::F32 zero = builder->splat(0.0f);
189         SkOverrideDeviceMatrixProvider matrixProvider(SkMatrix::I());
190         SkColorInfo colorInfo(kRGBA_8888_SkColorType, kPremul_SkAlphaType, /*cs=*/nullptr);
191
192         skvm::Color result = as_SB(fShader)->program(
193                 builder, /*device=*/coord, /*local=*/coord, /*paint=*/{zero, zero, zero, zero},
194                 matrixProvider, /*localM=*/nullptr, colorInfo, fUniforms,
195                 fAlloc);
196         SkASSERT(result);
197         outResult[0] = result.r;
198         outResult[1] = result.g;
199         outResult[2] = result.b;
200         outResult[3] = result.a;
201     }
202
203 private:
204     sk_sp<SkShader> fShader;
205 };
206
207 class SkImageBinding : public SkParticleBinding {
208 public:
209     SkImageBinding(const char* name = "", const char* imagePath = "", const char* imageName = "")
210             : SkParticleBinding(name)
211             , fImagePath(imagePath)
212             , fImageName(imageName) {}
213
214     REFLECTED(SkImageBinding, SkParticleBinding)
215
216     void visitFields(SkFieldVisitor* v) override {
217         SkParticleBinding::visitFields(v);
218         v->visit("ImagePath", fImagePath);
219         v->visit("ImageName", fImageName);
220     }
221
222     std::unique_ptr<SkParticleExternalFunction> toFunction(SkSL::Compiler& compiler,
223                                                            skvm::Uniforms* uniforms,
224                                                            SkArenaAlloc* alloc) override {
225         return std::make_unique<SkShaderExternalFunction>(fName.c_str(), compiler, fShader,
226                                                           uniforms, alloc);
227     }
228
229     void prepare(const skresources::ResourceProvider* resourceProvider) override {
230         SkASSERT(resourceProvider);
231         if (auto asset = resourceProvider->loadImageAsset(fImagePath.c_str(), fImageName.c_str(),
232                                                           nullptr)) {
233             SkASSERT(asset);
234             if (auto image = asset->getFrame(0)) {
235                 SkMatrix normalize = SkMatrix::Scale(1.0f / image->width(), 1.0f / image->height());
236                 fShader = image->makeShader(SkSamplingOptions(SkFilterMode::kLinear), &normalize);
237                 return;
238             }
239         }
240         fShader = SkShaders::Color(SK_ColorWHITE);
241     }
242
243 private:
244     SkString fImagePath;
245     SkString fImageName;
246
247     // Cached
248     sk_sp<SkShader> fShader;
249 };
250
251 sk_sp<SkParticleBinding> SkParticleBinding::MakeImage(const char* name, const char* imagePath,
252                                                       const char* imageName) {
253     return sk_sp<SkParticleBinding>(new SkImageBinding(name, imagePath, imageName));
254 }
255
256 sk_sp<SkParticleBinding> SkParticleBinding::MakePath(const char* name, const char* pathPath,
257                                                      const char* pathName) {
258     return sk_sp<SkParticleBinding>(new SkPathBinding(name, pathPath, pathName));
259 }
260
261 void SkParticleBinding::RegisterBindingTypes() {
262     REGISTER_REFLECTED(SkParticleBinding);
263     REGISTER_REFLECTED(SkImageBinding);
264     REGISTER_REFLECTED(SkPathBinding);
265     REGISTER_REFLECTED(SkTextBinding);
266 }