1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2020 Google LLC
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h"
9cb93a386Sopenharmony_ci#include "include/core/SkColor.h"
10cb93a386Sopenharmony_ci#include "include/core/SkImage.h"
11cb93a386Sopenharmony_ci#include "include/core/SkPaint.h"
12cb93a386Sopenharmony_ci#include "include/core/SkRect.h"
13cb93a386Sopenharmony_ci#include "include/core/SkSize.h"
14cb93a386Sopenharmony_ci#include "include/core/SkString.h"
15cb93a386Sopenharmony_ci#include "include/core/SkSurface.h"
16cb93a386Sopenharmony_ci#include "include/core/SkTypes.h"
17cb93a386Sopenharmony_ci#include "modules/skottie/include/Skottie.h"
18cb93a386Sopenharmony_ci#include "modules/sksg/include/SkSGInvalidationController.h"
19cb93a386Sopenharmony_ci
20cb93a386Sopenharmony_ci#include <string>
21cb93a386Sopenharmony_ci#include <vector>
22cb93a386Sopenharmony_ci
23cb93a386Sopenharmony_ci#include <emscripten.h>
24cb93a386Sopenharmony_ci#include <emscripten/bind.h>
25cb93a386Sopenharmony_ci
26cb93a386Sopenharmony_ci#if SK_INCLUDE_MANAGED_SKOTTIE
27cb93a386Sopenharmony_ci#include "modules/skottie/utils/SkottieUtils.h"
28cb93a386Sopenharmony_ci#include "modules/skresources/include/SkResources.h"
29cb93a386Sopenharmony_ci#endif // SK_INCLUDE_MANAGED_SKOTTIE
30cb93a386Sopenharmony_ci
31cb93a386Sopenharmony_ci#ifdef SK_GL
32cb93a386Sopenharmony_ci#include "include/core/SkImageInfo.h"
33cb93a386Sopenharmony_ci#include "include/gpu/GrBackendSurface.h"
34cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h"
35cb93a386Sopenharmony_ci#include "include/gpu/gl/GrGLInterface.h"
36cb93a386Sopenharmony_ci#include "include/gpu/gl/GrGLTypes.h"
37cb93a386Sopenharmony_ci
38cb93a386Sopenharmony_ci#include <GL/gl.h>
39cb93a386Sopenharmony_ci#include <emscripten/html5.h>
40cb93a386Sopenharmony_ci#endif
41cb93a386Sopenharmony_ci
42cb93a386Sopenharmony_ciusing namespace emscripten;
43cb93a386Sopenharmony_ci
44cb93a386Sopenharmony_ci// Self-documenting types
45cb93a386Sopenharmony_ciusing JSArray = emscripten::val;
46cb93a386Sopenharmony_ciusing JSObject = emscripten::val;
47cb93a386Sopenharmony_ciusing JSString = emscripten::val;
48cb93a386Sopenharmony_ciusing SkPathOrNull = emscripten::val;
49cb93a386Sopenharmony_ciusing Uint8Array = emscripten::val;
50cb93a386Sopenharmony_ciusing Float32Array = emscripten::val;
51cb93a386Sopenharmony_ci
52cb93a386Sopenharmony_ci#if SK_INCLUDE_MANAGED_SKOTTIE
53cb93a386Sopenharmony_cinamespace {
54cb93a386Sopenharmony_ci
55cb93a386Sopenharmony_ciclass SkottieAssetProvider : public skottie::ResourceProvider {
56cb93a386Sopenharmony_cipublic:
57cb93a386Sopenharmony_ci    ~SkottieAssetProvider() override = default;
58cb93a386Sopenharmony_ci
59cb93a386Sopenharmony_ci    // Tried using a map, but that gave strange errors like
60cb93a386Sopenharmony_ci    // https://emscripten.org/docs/porting/guidelines/function_pointer_issues.html
61cb93a386Sopenharmony_ci    // Not entirely sure why, but perhaps the iterator in the map was
62cb93a386Sopenharmony_ci    // confusing enscripten.
63cb93a386Sopenharmony_ci    using AssetVec = std::vector<std::pair<SkString, sk_sp<SkData>>>;
64cb93a386Sopenharmony_ci
65cb93a386Sopenharmony_ci    static sk_sp<SkottieAssetProvider> Make(AssetVec assets) {
66cb93a386Sopenharmony_ci        if (assets.empty()) {
67cb93a386Sopenharmony_ci            return nullptr;
68cb93a386Sopenharmony_ci        }
69cb93a386Sopenharmony_ci
70cb93a386Sopenharmony_ci        return sk_sp<SkottieAssetProvider>(new SkottieAssetProvider(std::move(assets)));
71cb93a386Sopenharmony_ci    }
72cb93a386Sopenharmony_ci
73cb93a386Sopenharmony_ci    sk_sp<skottie::ImageAsset> loadImageAsset(const char[] /* path */,
74cb93a386Sopenharmony_ci                                              const char name[],
75cb93a386Sopenharmony_ci                                              const char[] /* id */) const override {
76cb93a386Sopenharmony_ci        // For CK/Skottie we ignore paths & IDs, and identify images based solely on name.
77cb93a386Sopenharmony_ci        if (auto data = this->findAsset(name)) {
78cb93a386Sopenharmony_ci            return skresources::MultiFrameImageAsset::Make(std::move(data));
79cb93a386Sopenharmony_ci        }
80cb93a386Sopenharmony_ci
81cb93a386Sopenharmony_ci        return nullptr;
82cb93a386Sopenharmony_ci    }
83cb93a386Sopenharmony_ci
84cb93a386Sopenharmony_ci    sk_sp<SkData> loadFont(const char name[], const char[] /* url */) const override {
85cb93a386Sopenharmony_ci        // Same as images paths, we ignore font URLs.
86cb93a386Sopenharmony_ci        return this->findAsset(name);
87cb93a386Sopenharmony_ci    }
88cb93a386Sopenharmony_ci
89cb93a386Sopenharmony_ciprivate:
90cb93a386Sopenharmony_ci    explicit SkottieAssetProvider(AssetVec assets) : fAssets(std::move(assets)) {}
91cb93a386Sopenharmony_ci
92cb93a386Sopenharmony_ci    sk_sp<SkData> findAsset(const char name[]) const {
93cb93a386Sopenharmony_ci        for (const auto& asset : fAssets) {
94cb93a386Sopenharmony_ci            if (asset.first.equals(name)) {
95cb93a386Sopenharmony_ci                return asset.second;
96cb93a386Sopenharmony_ci            }
97cb93a386Sopenharmony_ci        }
98cb93a386Sopenharmony_ci
99cb93a386Sopenharmony_ci        SkDebugf("Could not find %s\n", name);
100cb93a386Sopenharmony_ci        return nullptr;
101cb93a386Sopenharmony_ci    }
102cb93a386Sopenharmony_ci
103cb93a386Sopenharmony_ci    const AssetVec fAssets;
104cb93a386Sopenharmony_ci};
105cb93a386Sopenharmony_ci
106cb93a386Sopenharmony_ciclass ManagedAnimation final : public SkRefCnt {
107cb93a386Sopenharmony_cipublic:
108cb93a386Sopenharmony_ci    static sk_sp<ManagedAnimation> Make(const std::string& json,
109cb93a386Sopenharmony_ci                                        sk_sp<skottie::ResourceProvider> rp) {
110cb93a386Sopenharmony_ci        auto mgr = std::make_unique<skottie_utils::CustomPropertyManager>();
111cb93a386Sopenharmony_ci        auto animation = skottie::Animation::Builder()
112cb93a386Sopenharmony_ci                            .setMarkerObserver(mgr->getMarkerObserver())
113cb93a386Sopenharmony_ci                            .setPropertyObserver(mgr->getPropertyObserver())
114cb93a386Sopenharmony_ci                            .setResourceProvider(rp)
115cb93a386Sopenharmony_ci                            .make(json.c_str(), json.size());
116cb93a386Sopenharmony_ci
117cb93a386Sopenharmony_ci        return animation
118cb93a386Sopenharmony_ci            ? sk_sp<ManagedAnimation>(new ManagedAnimation(std::move(animation), std::move(mgr)))
119cb93a386Sopenharmony_ci            : nullptr;
120cb93a386Sopenharmony_ci    }
121cb93a386Sopenharmony_ci
122cb93a386Sopenharmony_ci    ~ManagedAnimation() override = default;
123cb93a386Sopenharmony_ci
124cb93a386Sopenharmony_ci    // skottie::Animation API
125cb93a386Sopenharmony_ci    void render(SkCanvas* canvas) const { fAnimation->render(canvas, nullptr); }
126cb93a386Sopenharmony_ci    void render(SkCanvas* canvas, const SkRect& dst) const { fAnimation->render(canvas, &dst); }
127cb93a386Sopenharmony_ci    // Returns a damage rect.
128cb93a386Sopenharmony_ci    SkRect seek(SkScalar t) {
129cb93a386Sopenharmony_ci        sksg::InvalidationController ic;
130cb93a386Sopenharmony_ci        fAnimation->seek(t, &ic);
131cb93a386Sopenharmony_ci        return ic.bounds();
132cb93a386Sopenharmony_ci    }
133cb93a386Sopenharmony_ci    // Returns a damage rect.
134cb93a386Sopenharmony_ci    SkRect seekFrame(double t) {
135cb93a386Sopenharmony_ci        sksg::InvalidationController ic;
136cb93a386Sopenharmony_ci        fAnimation->seekFrame(t, &ic);
137cb93a386Sopenharmony_ci        return ic.bounds();
138cb93a386Sopenharmony_ci    }
139cb93a386Sopenharmony_ci    double duration() const { return fAnimation->duration(); }
140cb93a386Sopenharmony_ci    double fps() const { return fAnimation->fps(); }
141cb93a386Sopenharmony_ci    const SkSize& size() const { return fAnimation->size(); }
142cb93a386Sopenharmony_ci    std::string version() const { return std::string(fAnimation->version().c_str()); }
143cb93a386Sopenharmony_ci
144cb93a386Sopenharmony_ci    // CustomPropertyManager API
145cb93a386Sopenharmony_ci    JSArray getColorProps() const {
146cb93a386Sopenharmony_ci        JSArray props = emscripten::val::array();
147cb93a386Sopenharmony_ci
148cb93a386Sopenharmony_ci        for (const auto& cp : fPropMgr->getColorProps()) {
149cb93a386Sopenharmony_ci            JSObject prop = emscripten::val::object();
150cb93a386Sopenharmony_ci            prop.set("key", cp);
151cb93a386Sopenharmony_ci            prop.set("value", fPropMgr->getColor(cp));
152cb93a386Sopenharmony_ci            props.call<void>("push", prop);
153cb93a386Sopenharmony_ci        }
154cb93a386Sopenharmony_ci
155cb93a386Sopenharmony_ci        return props;
156cb93a386Sopenharmony_ci    }
157cb93a386Sopenharmony_ci
158cb93a386Sopenharmony_ci    JSArray getOpacityProps() const {
159cb93a386Sopenharmony_ci        JSArray props = emscripten::val::array();
160cb93a386Sopenharmony_ci
161cb93a386Sopenharmony_ci        for (const auto& op : fPropMgr->getOpacityProps()) {
162cb93a386Sopenharmony_ci            JSObject prop = emscripten::val::object();
163cb93a386Sopenharmony_ci            prop.set("key", op);
164cb93a386Sopenharmony_ci            prop.set("value", fPropMgr->getOpacity(op));
165cb93a386Sopenharmony_ci            props.call<void>("push", prop);
166cb93a386Sopenharmony_ci        }
167cb93a386Sopenharmony_ci
168cb93a386Sopenharmony_ci        return props;
169cb93a386Sopenharmony_ci    }
170cb93a386Sopenharmony_ci
171cb93a386Sopenharmony_ci    bool setColor(const std::string& key, SkColor c) {
172cb93a386Sopenharmony_ci        return fPropMgr->setColor(key, c);
173cb93a386Sopenharmony_ci    }
174cb93a386Sopenharmony_ci
175cb93a386Sopenharmony_ci    bool setOpacity(const std::string& key, float o) {
176cb93a386Sopenharmony_ci        return fPropMgr->setOpacity(key, o);
177cb93a386Sopenharmony_ci    }
178cb93a386Sopenharmony_ci
179cb93a386Sopenharmony_ci    JSArray getMarkers() const {
180cb93a386Sopenharmony_ci        JSArray markers = emscripten::val::array();
181cb93a386Sopenharmony_ci        for (const auto& m : fPropMgr->markers()) {
182cb93a386Sopenharmony_ci            JSObject marker = emscripten::val::object();
183cb93a386Sopenharmony_ci            marker.set("name", m.name);
184cb93a386Sopenharmony_ci            marker.set("t0"  , m.t0);
185cb93a386Sopenharmony_ci            marker.set("t1"  , m.t1);
186cb93a386Sopenharmony_ci            markers.call<void>("push", marker);
187cb93a386Sopenharmony_ci        }
188cb93a386Sopenharmony_ci        return markers;
189cb93a386Sopenharmony_ci    }
190cb93a386Sopenharmony_ci
191cb93a386Sopenharmony_ciprivate:
192cb93a386Sopenharmony_ci    ManagedAnimation(sk_sp<skottie::Animation> animation,
193cb93a386Sopenharmony_ci                     std::unique_ptr<skottie_utils::CustomPropertyManager> propMgr)
194cb93a386Sopenharmony_ci        : fAnimation(std::move(animation))
195cb93a386Sopenharmony_ci        , fPropMgr(std::move(propMgr)) {}
196cb93a386Sopenharmony_ci
197cb93a386Sopenharmony_ci    sk_sp<skottie::Animation>                             fAnimation;
198cb93a386Sopenharmony_ci    std::unique_ptr<skottie_utils::CustomPropertyManager> fPropMgr;
199cb93a386Sopenharmony_ci};
200cb93a386Sopenharmony_ci
201cb93a386Sopenharmony_ci} // anonymous ns
202cb93a386Sopenharmony_ci#endif // SK_INCLUDE_MANAGED_SKOTTIE
203cb93a386Sopenharmony_ci
204cb93a386Sopenharmony_cistruct SimpleImageInfo {
205cb93a386Sopenharmony_ci    int width;
206cb93a386Sopenharmony_ci    int height;
207cb93a386Sopenharmony_ci    SkColorType colorType;
208cb93a386Sopenharmony_ci    SkAlphaType alphaType;
209cb93a386Sopenharmony_ci    // TODO color spaces?
210cb93a386Sopenharmony_ci};
211cb93a386Sopenharmony_ci
212cb93a386Sopenharmony_ciSkImageInfo toSkImageInfo(const SimpleImageInfo& sii) {
213cb93a386Sopenharmony_ci    return SkImageInfo::Make(sii.width, sii.height, sii.colorType, sii.alphaType);
214cb93a386Sopenharmony_ci}
215cb93a386Sopenharmony_ci
216cb93a386Sopenharmony_ci#ifdef SK_GL
217cb93a386Sopenharmony_cisk_sp<GrDirectContext> MakeGrContext(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context)
218cb93a386Sopenharmony_ci{
219cb93a386Sopenharmony_ci    EMSCRIPTEN_RESULT r = emscripten_webgl_make_context_current(context);
220cb93a386Sopenharmony_ci    if (r < 0) {
221cb93a386Sopenharmony_ci        printf("failed to make webgl context current %d\n", r);
222cb93a386Sopenharmony_ci        return nullptr;
223cb93a386Sopenharmony_ci    }
224cb93a386Sopenharmony_ci    // setup GrDirectContext
225cb93a386Sopenharmony_ci    auto interface = GrGLMakeNativeInterface();
226cb93a386Sopenharmony_ci    return GrDirectContext::MakeGL(interface);
227cb93a386Sopenharmony_ci}
228cb93a386Sopenharmony_ci
229cb93a386Sopenharmony_cisk_sp<SkSurface> MakeOnScreenGLSurface(sk_sp<GrDirectContext> grContext, int width, int height) {
230cb93a386Sopenharmony_ci    glClearColor(0, 0, 0, 0);
231cb93a386Sopenharmony_ci    glClearStencil(0);
232cb93a386Sopenharmony_ci    glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
233cb93a386Sopenharmony_ci
234cb93a386Sopenharmony_ci
235cb93a386Sopenharmony_ci    // Wrap the frame buffer object attached to the screen in a Skia render
236cb93a386Sopenharmony_ci    // target so Skia can render to it
237cb93a386Sopenharmony_ci    GrGLint buffer;
238cb93a386Sopenharmony_ci    glGetIntegerv(GL_FRAMEBUFFER_BINDING, &buffer);
239cb93a386Sopenharmony_ci    GrGLFramebufferInfo info;
240cb93a386Sopenharmony_ci    info.fFBOID = (GrGLuint) buffer;
241cb93a386Sopenharmony_ci    SkColorType colorType;
242cb93a386Sopenharmony_ci
243cb93a386Sopenharmony_ci    GrGLint stencil;
244cb93a386Sopenharmony_ci    glGetIntegerv(GL_STENCIL_BITS, &stencil);
245cb93a386Sopenharmony_ci
246cb93a386Sopenharmony_ci    info.fFormat = GL_RGBA8;
247cb93a386Sopenharmony_ci    colorType = kRGBA_8888_SkColorType;
248cb93a386Sopenharmony_ci
249cb93a386Sopenharmony_ci    GrBackendRenderTarget target(width, height, 0, stencil, info);
250cb93a386Sopenharmony_ci
251cb93a386Sopenharmony_ci    sk_sp<SkSurface> surface(SkSurface::MakeFromBackendRenderTarget(grContext.get(), target,
252cb93a386Sopenharmony_ci                                                                    kBottomLeft_GrSurfaceOrigin,
253cb93a386Sopenharmony_ci                                                                    colorType, nullptr, nullptr));
254cb93a386Sopenharmony_ci    return surface;
255cb93a386Sopenharmony_ci}
256cb93a386Sopenharmony_ci
257cb93a386Sopenharmony_cisk_sp<SkSurface> MakeRenderTarget(sk_sp<GrDirectContext> grContext, int width, int height) {
258cb93a386Sopenharmony_ci    SkImageInfo info = SkImageInfo::MakeN32(width, height, SkAlphaType::kPremul_SkAlphaType);
259cb93a386Sopenharmony_ci
260cb93a386Sopenharmony_ci    sk_sp<SkSurface> surface(SkSurface::MakeRenderTarget(grContext.get(),
261cb93a386Sopenharmony_ci                             SkBudgeted::kYes,
262cb93a386Sopenharmony_ci                             info, 0,
263cb93a386Sopenharmony_ci                             kBottomLeft_GrSurfaceOrigin,
264cb93a386Sopenharmony_ci                             nullptr, true));
265cb93a386Sopenharmony_ci    return surface;
266cb93a386Sopenharmony_ci}
267cb93a386Sopenharmony_ci
268cb93a386Sopenharmony_cisk_sp<SkSurface> MakeRenderTarget(sk_sp<GrDirectContext> grContext, SimpleImageInfo sii) {
269cb93a386Sopenharmony_ci    sk_sp<SkSurface> surface(SkSurface::MakeRenderTarget(grContext.get(),
270cb93a386Sopenharmony_ci                             SkBudgeted::kYes,
271cb93a386Sopenharmony_ci                             toSkImageInfo(sii), 0,
272cb93a386Sopenharmony_ci                             kBottomLeft_GrSurfaceOrigin,
273cb93a386Sopenharmony_ci                             nullptr, true));
274cb93a386Sopenharmony_ci    return surface;
275cb93a386Sopenharmony_ci}
276cb93a386Sopenharmony_ci#endif // SK_GL
277cb93a386Sopenharmony_ci
278cb93a386Sopenharmony_ci// Some signatures below have uintptr_t instead of a pointer to a primitive
279cb93a386Sopenharmony_ci// type (e.g. SkScalar). This is necessary because we can't use "bind" (EMSCRIPTEN_BINDINGS)
280cb93a386Sopenharmony_ci// and pointers to primitive types (Only bound types like SkPoint). We could if we used
281cb93a386Sopenharmony_ci// cwrap (see https://becominghuman.ai/passing-and-returning-webassembly-array-parameters-a0f572c65d97)
282cb93a386Sopenharmony_ci// but that requires us to stick to C code and, AFAIK, doesn't allow us to return nice things like
283cb93a386Sopenharmony_ci// SkPath or SkCanvas.
284cb93a386Sopenharmony_ci//
285cb93a386Sopenharmony_ci// So, basically, if we are using C++ and EMSCRIPTEN_BINDINGS, we can't have primitive pointers
286cb93a386Sopenharmony_ci// in our function type signatures. (this gives an error message like "Cannot call foo due to unbound
287cb93a386Sopenharmony_ci// types Pi, Pf").  But, we can just pretend they are numbers and cast them to be pointers and
288cb93a386Sopenharmony_ci// the compiler is happy.
289cb93a386Sopenharmony_ciEMSCRIPTEN_BINDINGS(Skottie) {
290cb93a386Sopenharmony_ci#ifdef SK_GL
291cb93a386Sopenharmony_ci    function("currentContext", &emscripten_webgl_get_current_context);
292cb93a386Sopenharmony_ci    function("setCurrentContext", &emscripten_webgl_make_context_current);
293cb93a386Sopenharmony_ci    function("MakeGrContext", &MakeGrContext);
294cb93a386Sopenharmony_ci    function("MakeOnScreenGLSurface", &MakeOnScreenGLSurface);
295cb93a386Sopenharmony_ci    function("MakeRenderTarget",
296cb93a386Sopenharmony_ci        select_overload<sk_sp<SkSurface>(sk_sp<GrDirectContext>, int, int)>(&MakeRenderTarget));
297cb93a386Sopenharmony_ci    function("MakeRenderTarget",
298cb93a386Sopenharmony_ci        select_overload<sk_sp<SkSurface>(sk_sp<GrDirectContext>, SimpleImageInfo)>(&MakeRenderTarget));
299cb93a386Sopenharmony_ci
300cb93a386Sopenharmony_ci    constant("gpu", true);
301cb93a386Sopenharmony_ci
302cb93a386Sopenharmony_ci    class_<GrDirectContext>("GrDirectContext")
303cb93a386Sopenharmony_ci    .smart_ptr<sk_sp<GrDirectContext>>("sk_sp<GrDirectContext>");
304cb93a386Sopenharmony_ci    // .function("getResourceCacheLimitBytes", optional_override([](GrDirectContext& self)->size_t {
305cb93a386Sopenharmony_ci    //     int maxResources = 0;// ignored
306cb93a386Sopenharmony_ci    //     size_t currMax = 0;
307cb93a386Sopenharmony_ci    //     self.getResourceCacheLimits(&maxResources, &currMax);
308cb93a386Sopenharmony_ci    //     return currMax;
309cb93a386Sopenharmony_ci    // }))
310cb93a386Sopenharmony_ci    // .function("getResourceCacheUsageBytes", optional_override([](GrDirectContext& self)->size_t {
311cb93a386Sopenharmony_ci    //     int usedResources = 0;// ignored
312cb93a386Sopenharmony_ci    //     size_t currUsage = 0;
313cb93a386Sopenharmony_ci    //     self.getResourceCacheUsage(&usedResources, &currUsage);
314cb93a386Sopenharmony_ci    //     return currUsage;
315cb93a386Sopenharmony_ci    // }))
316cb93a386Sopenharmony_ci    // .function("releaseResourcesAndAbandonContext", &GrDirectContext::releaseResourcesAndAbandonContext)
317cb93a386Sopenharmony_ci    // .function("setResourceCacheLimitBytes", optional_override([](GrDirectContext& self, size_t maxResourceBytes) {
318cb93a386Sopenharmony_ci    //     int maxResources = 0;
319cb93a386Sopenharmony_ci    //     size_t currMax = 0; // ignored
320cb93a386Sopenharmony_ci    //     self.getResourceCacheLimits(&maxResources, &currMax);
321cb93a386Sopenharmony_ci    //     self.setResourceCacheLimits(maxResources, maxResourceBytes);
322cb93a386Sopenharmony_ci    // }));
323cb93a386Sopenharmony_ci#endif
324cb93a386Sopenharmony_ci
325cb93a386Sopenharmony_ci    // function("getDecodeCacheLimitBytes", &SkResourceCache::GetTotalByteLimit);
326cb93a386Sopenharmony_ci    // function("setDecodeCacheLimitBytes", &SkResourceCache::SetTotalByteLimit);
327cb93a386Sopenharmony_ci    // function("getDecodeCacheUsedBytes" , &SkResourceCache::GetTotalBytesUsed);
328cb93a386Sopenharmony_ci
329cb93a386Sopenharmony_ci    function("_getRasterDirectSurface", optional_override([](const SimpleImageInfo ii,
330cb93a386Sopenharmony_ci                                                             uintptr_t /* uint8_t*  */ pPtr,
331cb93a386Sopenharmony_ci                                                             size_t rowBytes)->sk_sp<SkSurface> {
332cb93a386Sopenharmony_ci        uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr);
333cb93a386Sopenharmony_ci        SkImageInfo imageInfo = toSkImageInfo(ii);
334cb93a386Sopenharmony_ci        return SkSurface::MakeRasterDirect(imageInfo, pixels, rowBytes, nullptr);
335cb93a386Sopenharmony_ci    }), allow_raw_pointers());
336cb93a386Sopenharmony_ci
337cb93a386Sopenharmony_ci    class_<SkCanvas>("SkCanvas")
338cb93a386Sopenharmony_ci        .function("_clear", optional_override([](SkCanvas& self, uintptr_t /* float* */ cPtr) {
339cb93a386Sopenharmony_ci            // See comment above for uintptr_t explanation
340cb93a386Sopenharmony_ci            float* fourFloats = reinterpret_cast<float*>(cPtr);
341cb93a386Sopenharmony_ci            SkColor4f color = { fourFloats[0], fourFloats[1], fourFloats[2], fourFloats[3]};
342cb93a386Sopenharmony_ci            // TODO(reed): SkCanvas.clear() should take SkColor4f, then we could just use it here.
343cb93a386Sopenharmony_ci            SkPaint p;
344cb93a386Sopenharmony_ci            p.setBlendMode(SkBlendMode::kSrc);
345cb93a386Sopenharmony_ci            p.setColor4f(color);
346cb93a386Sopenharmony_ci            self.drawPaint(p);
347cb93a386Sopenharmony_ci        }));
348cb93a386Sopenharmony_ci
349cb93a386Sopenharmony_ci    class_<SkSurface>("SkSurface")
350cb93a386Sopenharmony_ci        .smart_ptr<sk_sp<SkSurface>>("sk_sp<SkSurface>")
351cb93a386Sopenharmony_ci        .function("_flush", select_overload<void()>(&SkSurface::flush))
352cb93a386Sopenharmony_ci        .function("getCanvas", &SkSurface::getCanvas, allow_raw_pointers());
353cb93a386Sopenharmony_ci
354cb93a386Sopenharmony_ci    class_<skottie::Animation>("Animation")
355cb93a386Sopenharmony_ci        .smart_ptr<sk_sp<skottie::Animation>>("sk_sp<Animation>")
356cb93a386Sopenharmony_ci        .function("version", optional_override([](skottie::Animation& self)->std::string {
357cb93a386Sopenharmony_ci            return std::string(self.version().c_str());
358cb93a386Sopenharmony_ci        }))
359cb93a386Sopenharmony_ci        .function("size"    , &skottie::Animation::size)
360cb93a386Sopenharmony_ci        .function("duration", &skottie::Animation::duration)
361cb93a386Sopenharmony_ci        .function("fps"     , &skottie::Animation::fps)
362cb93a386Sopenharmony_ci        .function("seek", optional_override([](skottie::Animation& self, SkScalar t)->void {
363cb93a386Sopenharmony_ci            self.seek(t);
364cb93a386Sopenharmony_ci        }))
365cb93a386Sopenharmony_ci        .function("seekFrame", optional_override([](skottie::Animation& self, double t)->void {
366cb93a386Sopenharmony_ci            self.seekFrame(t);
367cb93a386Sopenharmony_ci        }))
368cb93a386Sopenharmony_ci        .function("render", optional_override([](skottie::Animation& self, SkCanvas* canvas)->void {
369cb93a386Sopenharmony_ci            self.render(canvas, nullptr);
370cb93a386Sopenharmony_ci        }), allow_raw_pointers())
371cb93a386Sopenharmony_ci        .function("render", optional_override([](skottie::Animation& self, SkCanvas* canvas,
372cb93a386Sopenharmony_ci                                                 const SkRect r)->void {
373cb93a386Sopenharmony_ci            self.render(canvas, &r);
374cb93a386Sopenharmony_ci        }), allow_raw_pointers());
375cb93a386Sopenharmony_ci
376cb93a386Sopenharmony_ci    function("MakeAnimation", optional_override([](std::string json)->sk_sp<skottie::Animation> {
377cb93a386Sopenharmony_ci        return skottie::Animation::Make(json.c_str(), json.length());
378cb93a386Sopenharmony_ci    }));
379cb93a386Sopenharmony_ci    constant("skottie", true);
380cb93a386Sopenharmony_ci
381cb93a386Sopenharmony_ci#if SK_INCLUDE_MANAGED_SKOTTIE
382cb93a386Sopenharmony_ci    class_<ManagedAnimation>("ManagedAnimation")
383cb93a386Sopenharmony_ci        .smart_ptr<sk_sp<ManagedAnimation>>("sk_sp<ManagedAnimation>")
384cb93a386Sopenharmony_ci        .function("version"   , &ManagedAnimation::version)
385cb93a386Sopenharmony_ci        .function("size"      , &ManagedAnimation::size)
386cb93a386Sopenharmony_ci        .function("duration"  , &ManagedAnimation::duration)
387cb93a386Sopenharmony_ci        .function("fps"       , &ManagedAnimation::fps)
388cb93a386Sopenharmony_ci        .function("seek"      , &ManagedAnimation::seek)
389cb93a386Sopenharmony_ci        .function("seekFrame" , &ManagedAnimation::seekFrame)
390cb93a386Sopenharmony_ci        .function("render"    , select_overload<void(SkCanvas*) const>(&ManagedAnimation::render), allow_raw_pointers())
391cb93a386Sopenharmony_ci        .function("render"    , select_overload<void(SkCanvas*, const SkRect&) const>
392cb93a386Sopenharmony_ci                                    (&ManagedAnimation::render), allow_raw_pointers());
393cb93a386Sopenharmony_ci        // .function("setColor"  , optional_override([](ManagedAnimation& self, const std::string& key, SimpleColor4f c) {
394cb93a386Sopenharmony_ci        //     self.setColor(key, c.toSkColor());
395cb93a386Sopenharmony_ci        // }))
396cb93a386Sopenharmony_ci        // .function("setOpacity", &ManagedAnimation::setOpacity)
397cb93a386Sopenharmony_ci        // .function("getMarkers", &ManagedAnimation::getMarkers)
398cb93a386Sopenharmony_ci        // .function("getColorProps"  , &ManagedAnimation::getColorProps)
399cb93a386Sopenharmony_ci        // .function("getOpacityProps", &ManagedAnimation::getOpacityProps);
400cb93a386Sopenharmony_ci
401cb93a386Sopenharmony_ci    function("_MakeManagedAnimation", optional_override([](std::string json,
402cb93a386Sopenharmony_ci                                                           size_t assetCount,
403cb93a386Sopenharmony_ci                                                           uintptr_t /* char**     */ nptr,
404cb93a386Sopenharmony_ci                                                           uintptr_t /* uint8_t**  */ dptr,
405cb93a386Sopenharmony_ci                                                           uintptr_t /* size_t*    */ sptr)
406cb93a386Sopenharmony_ci                                                        ->sk_sp<ManagedAnimation> {
407cb93a386Sopenharmony_ci        // See the comment in canvaskit_bindings.cpp about the use of uintptr_t
408cb93a386Sopenharmony_ci        const auto assetNames = reinterpret_cast<char**   >(nptr);
409cb93a386Sopenharmony_ci        const auto assetDatas = reinterpret_cast<uint8_t**>(dptr);
410cb93a386Sopenharmony_ci        const auto assetSizes = reinterpret_cast<size_t*  >(sptr);
411cb93a386Sopenharmony_ci
412cb93a386Sopenharmony_ci        SkottieAssetProvider::AssetVec assets;
413cb93a386Sopenharmony_ci        assets.reserve(assetCount);
414cb93a386Sopenharmony_ci
415cb93a386Sopenharmony_ci        for (size_t i = 0; i < assetCount; i++) {
416cb93a386Sopenharmony_ci            auto name  = SkString(assetNames[i]);
417cb93a386Sopenharmony_ci            auto bytes = SkData::MakeFromMalloc(assetDatas[i], assetSizes[i]);
418cb93a386Sopenharmony_ci            assets.push_back(std::make_pair(std::move(name), std::move(bytes)));
419cb93a386Sopenharmony_ci        }
420cb93a386Sopenharmony_ci
421cb93a386Sopenharmony_ci        return ManagedAnimation::Make(json,
422cb93a386Sopenharmony_ci                 skresources::DataURIResourceProviderProxy::Make(
423cb93a386Sopenharmony_ci                    SkottieAssetProvider::Make(std::move(assets))));
424cb93a386Sopenharmony_ci    }));
425cb93a386Sopenharmony_ci    constant("managed_skottie", true);
426cb93a386Sopenharmony_ci#endif // SK_INCLUDE_MANAGED_SKOTTIE
427cb93a386Sopenharmony_ci
428cb93a386Sopenharmony_ci    value_object<SimpleImageInfo>("SkImageInfo")
429cb93a386Sopenharmony_ci        .field("width",     &SimpleImageInfo::width)
430cb93a386Sopenharmony_ci        .field("height",    &SimpleImageInfo::height)
431cb93a386Sopenharmony_ci        .field("colorType", &SimpleImageInfo::colorType)
432cb93a386Sopenharmony_ci        .field("alphaType", &SimpleImageInfo::alphaType);
433cb93a386Sopenharmony_ci
434cb93a386Sopenharmony_ci    value_object<SkRect>("SkRect")
435cb93a386Sopenharmony_ci        .field("fLeft",   &SkRect::fLeft)
436cb93a386Sopenharmony_ci        .field("fTop",    &SkRect::fTop)
437cb93a386Sopenharmony_ci        .field("fRight",  &SkRect::fRight)
438cb93a386Sopenharmony_ci        .field("fBottom", &SkRect::fBottom);
439cb93a386Sopenharmony_ci
440cb93a386Sopenharmony_ci    // {"w": Number, "h", Number}
441cb93a386Sopenharmony_ci    value_object<SkSize>("SkSize")
442cb93a386Sopenharmony_ci        .field("w",   &SkSize::fWidth)
443cb93a386Sopenharmony_ci        .field("h",   &SkSize::fHeight);
444cb93a386Sopenharmony_ci
445cb93a386Sopenharmony_ci    enum_<SkAlphaType>("AlphaType")
446cb93a386Sopenharmony_ci        .value("Opaque",   SkAlphaType::kOpaque_SkAlphaType)
447cb93a386Sopenharmony_ci        .value("Premul",   SkAlphaType::kPremul_SkAlphaType)
448cb93a386Sopenharmony_ci        .value("Unpremul", SkAlphaType::kUnpremul_SkAlphaType);
449cb93a386Sopenharmony_ci
450cb93a386Sopenharmony_ci    enum_<SkColorType>("ColorType")
451cb93a386Sopenharmony_ci        .value("RGBA_8888", SkColorType::kRGBA_8888_SkColorType);
452cb93a386Sopenharmony_ci
453cb93a386Sopenharmony_ci}
454