e0aa7605f2
Bug: skia: Change-Id: I20d61933dd11c4cc7cc64baee8abf93372124cdd Reviewed-on: https://skia-review.googlesource.com/c/skia/+/198166 Reviewed-by: Kevin Lubick <kjlubick@google.com> Commit-Queue: Nathaniel Nifong <nifong@google.com>
113 lines
4.2 KiB
C++
113 lines
4.2 KiB
C++
/*
|
|
* 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() {}
|
|
|
|
|
|
/* loadSkp deserializes a skp file that has been copied into the shared WASM memory.
|
|
* cptr - a pointer to the data to deserialize.
|
|
* length - length of the data in bytes.
|
|
* The caller must allocate the memory with M._malloc where M is the wasm module in javascript
|
|
* and copy the data into M.buffer at the pointer returned by malloc.
|
|
*
|
|
* uintptr_t is used here because emscripten will not allow binding of functions with pointers
|
|
* to primitive types. We can instead pass a number and cast it to whatever kind of
|
|
* pointer we're expecting.
|
|
*/
|
|
void loadSkp(uintptr_t cptr, int length) {
|
|
const auto* data = reinterpret_cast<const uint8_t*>(cptr);
|
|
// todo: pass in bounds
|
|
fDebugCanvas.reset(new SkDebugCanvas(720, 1280));
|
|
SkDebugf("SkDebugCanvas created.\n");
|
|
// note overloaded = operator that actually does a move
|
|
fPicture = SkPicture::MakeFromData(data, length);
|
|
if (!fPicture) {
|
|
SkDebugf("Unable to parse SKP file.\n");
|
|
return;
|
|
}
|
|
SkDebugf("Parsed SKP file.\n");
|
|
// Only draw picture to the debug canvas once.
|
|
fDebugCanvas->drawPicture(fPicture);
|
|
SkDebugf("Added picture with %d commands.\n", fDebugCanvas->getSize());
|
|
}
|
|
|
|
/* drawTo asks the debug canvas to draw from the beginning of the picture
|
|
* to the given command and flush the canvas.
|
|
*/
|
|
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, allow_raw_pointers())
|
|
.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));
|
|
}));
|
|
}
|