| /* |
| * Copyright 2019 Google LLC |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "SkDebugCanvas.h" |
| #include "SkPicture.h" |
| #include "SkSurface.h" |
| #include <emscripten.h> |
| #include <emscripten/bind.h> |
| |
| using JSColor = int32_t; |
| |
| struct SimpleImageInfo { |
| int width; |
| int height; |
| SkColorType colorType; |
| SkAlphaType alphaType; |
| }; |
| |
| SkImageInfo toSkImageInfo(const SimpleImageInfo& sii) { |
| return SkImageInfo::Make(sii.width, sii.height, sii.colorType, sii.alphaType); |
| } |
| |
| class SkpDebugPlayer { |
| public: |
| SkpDebugPlayer() {} |
| |
| void loadSkp() { |
| // todo: pass in bounds |
| fDebugCanvas.reset(new SkDebugCanvas(720, 1280)); |
| SkDebugf("SkDebugCanvas created.\n"); |
| // load and parse skp file that was included with --preload-file |
| auto fromfile = SkStream::MakeFromFile("experimental/wasm-skp-debugger/sample.skp"); |
| // note overloaded = operator that actually does a move |
| fPicture = SkPicture::MakeFromStream(fromfile.get()); |
| SkDebugf("parsed skp file.\n"); |
| // Only draw picture to the debug canvas once. |
| fDebugCanvas->drawPicture(fPicture); |
| SkDebugf("drew picture with %d commands.\n", fDebugCanvas->getSize()); |
| } |
| |
| void drawTo(SkSurface* surface, int32_t index) { |
| fDebugCanvas->drawTo(surface->getCanvas(), index); |
| surface->getCanvas()->flush(); |
| } |
| |
| private: |
| // admission of ignorance - don't know when to use unique pointer or sk_sp |
| std::unique_ptr<SkDebugCanvas> fDebugCanvas; |
| sk_sp<SkPicture> fPicture; |
| }; |
| |
| using namespace emscripten; |
| EMSCRIPTEN_BINDINGS(my_module) { |
| |
| // The main class that the JavaScript in index.html uses |
| class_<SkpDebugPlayer>("SkpDebugPlayer") |
| .constructor<>() |
| .function("loadSkp", &SkpDebugPlayer::loadSkp) |
| .function("drawTo", &SkpDebugPlayer::drawTo, allow_raw_pointers()); |
| |
| // Symbols needed by cpu.js to perform surface creation and flushing. |
| enum_<SkColorType>("ColorType") |
| .value("RGBA_8888", SkColorType::kRGBA_8888_SkColorType); |
| enum_<SkAlphaType>("AlphaType") |
| .value("Unpremul", SkAlphaType::kUnpremul_SkAlphaType); |
| value_object<SimpleImageInfo>("SkImageInfo") |
| .field("width", &SimpleImageInfo::width) |
| .field("height", &SimpleImageInfo::height) |
| .field("colorType", &SimpleImageInfo::colorType) |
| .field("alphaType", &SimpleImageInfo::alphaType); |
| constant("TRANSPARENT", (JSColor) SK_ColorTRANSPARENT); |
| function("_getRasterDirectSurface", optional_override([](const SimpleImageInfo ii, |
| uintptr_t /* uint8_t* */ pPtr, |
| size_t rowBytes)->sk_sp<SkSurface> { |
| uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr); |
| SkImageInfo imageInfo = toSkImageInfo(ii); |
| return SkSurface::MakeRasterDirect(imageInfo, pixels, rowBytes, nullptr); |
| }), allow_raw_pointers()); |
| class_<SkSurface>("SkSurface") |
| .smart_ptr<sk_sp<SkSurface>>("sk_sp<SkSurface>") |
| .function("width", &SkSurface::width) |
| .function("height", &SkSurface::height) |
| .function("_flush", select_overload<void()>(&SkSurface::flush)) |
| .function("getCanvas", &SkSurface::getCanvas, allow_raw_pointers()); |
| class_<SkCanvas>("SkCanvas") |
| .function("clear", optional_override([](SkCanvas& self, JSColor color)->void { |
| // JS side gives us a signed int instead of an unsigned int for color |
| // Add a optional_override to change it out. |
| self.clear(SkColor(color)); |
| })); |
| } |