/*
 * Copyright 2022 Rive
 */
#include "testing_window.hpp"

#if !defined(RIVE_CANVAS_2D)

TestingWindow* TestingWindow::MakeCanvas2D() { return nullptr; }

#else

#include "utils/factory_utils.hpp"

#include <string>
#include <vector>

#include <emscripten/emscripten.h>
#include <emscripten/html5.h>
#include <emscripten/val.h>

namespace rive::gpu
{

EM_ASYNC_JS(void, testingWindowCanvas2dImportCanvasAdvanced, (), {
  // clang-format off
    if (globalThis.canvasAdvancedModule === undefined)
    {
        const result = await import("./canvas_advanced.mjs");
        globalThis.canvasAdvancedModule = await result.default();
    }
  // clang-format on
});

// Resets the canvas and fills it with `color` (0xAARRGGBB)
EM_JS(void, testingWindowCanvas2dResetCanvas, (uint32_t color), {
  var canvas = document["getElementById"]("canvas");
  var ctx = canvas["getContext"]("2d");
  ctx["reset"]();
  // reset() leaves the canvas transparent, so compositing the clear color
  // over it yields that color, alpha included.
  ctx["fillStyle"] = "rgba(" + ((0x00ff0000 & color) >>> 16) + "," +
                     ((0x0000ff00 & color) >>> 8) + "," +
                     ((0x000000ff & color) >>> 0) + "," +
                     ((0xff000000 & color) >>> 24) / 0xff + ")";
  ctx["fillRect"](0, 0, canvas["width"], canvas["height"]);
});

EM_JS(
    bool,
    testingWindowCanvas2dGetCanvasPixels,
    (uint8_t* outBuffer, int width, int height),
    {
      var canvas = document["getElementById"]("canvas");
      var ctx = canvas["getContext"]("2d");
      var imageData = ctx["getImageData"](0, 0, canvas.width, canvas.height);
      var pixelArray = imageData["data"];
      if (pixelArray.length != width * height * 4)
      {
        return false;
      }

      // TestHarness::savePNG() reads this buffer bottom-up, the GL
      // convention every other backend fills it with. getImageData()
      // returns rows top-down, so reverse them here.
      var stride = width * 4;
      for (var y = 0; y < height; ++y)
      {
        Module['HEAPU8']['set'](
            pixelArray['subarray'](
                (height - 1 - y) * stride,
                (height - y) * stride),
            outBuffer + y * stride);
      }
      return true;
    });

// Image decoding is asynchronous. renderer.js hands the bytes to an <img>
// element through a blob URL and fills in the result on its load event, so this
// awaits that event and returns the image as a value handle.
//
// Module.decodeImage is the entry point that works here.
// renderFactory.makeRenderImage()'s onDecode callback closes over renderer.js's
// loadContext, which is null outside Module.load(), and this harness draws
// images without ever loading a .riv file.
EM_ASYNC_JS(
    emscripten::EM_VAL,
    testingWindowCanvas2dDecodeImage,
    (const uint8_t* bytes, int size),
    {
      // Defensive copy out of this module's heap; renderer.js's
      // `decode` copies the bytes into a Blob as well.
      var copy = Module['HEAPU8']['slice'](bytes, bytes + size);
      var image = await new Promise(function(resolve) {
        globalThis.canvasAdvancedModule["decodeImage"](copy, resolve);
      });
      return Emval.toHandle(image);
    });

// Resolved on first use because the module is not on globalThis until
// testingWindowCanvas2dImportCanvasAdvanced() has finished.
static emscripten::val& canvasAdvancedModule()
{
  static emscripten::val module = emscripten::val::global(
      "canvasAdvancedModule");
  return module;
}

// embind exposes C++ enums to JS as value objects, and renderer.js compares
// them by identity, so calls into it have to carry canvas_advanced's own
// objects. This class maps a C++ enumerator to the matching object, reading the
// table embind stores on the enum's JS constructor as `.values[rawValue]` (see
// _embind_register_enum_value in libembind.js).
class JSEnum
{
public:
  // Must not be constructed until canvas_advanced.mjs has finished loading.
  explicit JSEnum(const char* enumName)
  {
    emscripten::val values = canvasAdvancedModule()[enumName]["values"];
    assert(!values.isUndefined()); // Not an embind enum?

    // Indexed by raw value. These enums are sparse, so the gaps stay
    // undefined and operator() asserts on them.
    emscripten::val keys = emscripten::val::global("Object")
                               .call<emscripten::val>("keys", values);
    size_t keyCount = keys["length"].as<size_t>();
    for (size_t i = 0; i < keyCount; i++)
    {
      int rawValue = std::stoi(keys[i].as<std::string>());
      assert(rawValue >= 0);

      // m_values is a dense vector, so an enum with large raw values,
      // such as a bit-mask, would make it huge.
      assert(rawValue < 1024);

      if (static_cast<size_t>(rawValue) >= m_values.size())
      {
        m_values.resize(rawValue + 1, emscripten::val::undefined());
      }
      m_values[rawValue] = values[rawValue];
    }
  }

  template <typename T> const emscripten::val& operator()(T value) const
  {
    size_t rawValue = static_cast<size_t>(value);
    assert(rawValue < m_values.size());
    assert(!m_values[rawValue].isUndefined());
    return m_values[rawValue];
  }

private:
  std::vector<emscripten::val> m_values;
};

// These strings are the names canvas_advanced registers in
// EMSCRIPTEN_BINDINGS(RiveWASM_C2D), which need not match the C++ type names.
struct JSEnums
{
  JSEnum blendMode{"BlendMode"};
  JSEnum fillRule{"FillRule"};
  JSEnum paintStyle{"RenderPaintStyle"};
  JSEnum strokeCap{"StrokeCap"};
  JSEnum strokeJoin{"StrokeJoin"};
  JSEnum strokePosition{"StrokePosition"};
  JSEnum imageFilter{"ImageFilter"};
  JSEnum imageWrap{"ImageWrap"};
};

// Built on first use, which must come after the
// testingWindowCanvas2dImportCanvasAdvanced() call in TestingWindowCanvas2D's
// constructor.
static const JSEnums& jsEnums()
{
  static JSEnums enums;
  return enums;
}

// The classes below drive the canvas2d renderer that lives in
// canvas_advanced.mjs.
//
// This harness and canvas_advanced are separately linked Emscripten modules,
// each with its own WebAssembly.Memory, C++ runtime and embind type registry. A
// pointer is an offset into one module's linear memory, so nothing that is or
// contains one -- a rive::Renderer*, an rcp<>, a vtable -- can be handed
// across. JS objects can, since there is one JavaScript realm; that includes
// TypedArrays, which are ordinary JS objects that view a particular module's
// heap.
//
// So each class holds the emscripten::val of its canvas_advanced counterpart
// and forwards to it, either directly (m_jsPath.call<void>("moveTo", x, y)) or
// through Canvas2DTestUtilities, which wraps the calls whose logic the harness
// would otherwise have to duplicate.
//
// The JS handle stays the sole owner of each object, and embind never reclaims
// raw pointer handles by itself, so every destructor here releases explicitly.
// It calls deleteLater(), since renderer.js captures paths and paints in
// deferred draw-list closures that must outlive the C++ object until endFrame()
// flushes them.
//
// Every renderer object here originates from JSRenderFactory, so a failed
// downcast is a bug; hence lite_rtti_cast_or_assert<> over the silent
// LITE_RTTI_CAST_OR_* macros.

// Gradients have no JS-side object to wrap, so there is no handle for
// makeLinearGradient() to return. These hold the parameters and replay them
// onto the paint from JSRenderPaint::shader(), mirroring Canvas2DGradientShader
// in bindings_c2d.cpp.
class JSGradientShader
    : public LITE_RTTI_OVERRIDE(RenderShader, JSGradientShader)
{
public:
  JSGradientShader(const ColorInt colors[], const float stops[], size_t count)
      : m_stops(stops, stops + count)
      , m_colors(colors, colors + count)
  {}

  virtual void applyToPaint(const emscripten::val& jsPaint) const = 0;

protected:
  void applyStopsToPaint(const emscripten::val& jsPaint) const
  {
    for (size_t i = 0; i < m_stops.size(); ++i)
    {
      jsPaint.call<void>("addStop", m_colors[i], m_stops[i]);
    }
  }

private:
  std::vector<float> m_stops;
  std::vector<ColorInt> m_colors;
};

class JSLinearGradientShader : public JSGradientShader
{
public:
  JSLinearGradientShader(
      const ColorInt colors[],
      const float stops[],
      size_t count,
      float sx,
      float sy,
      float ex,
      float ey)
      : JSGradientShader(colors, stops, count)
      , m_startX(sx)
      , m_startY(sy)
      , m_endX(ex)
      , m_endY(ey)
  {}

  void applyToPaint(const emscripten::val& jsPaint) const override
  {
    jsPaint.call<void>("linearGradient", m_startX, m_startY, m_endX, m_endY);
    applyStopsToPaint(jsPaint);
  }

private:
  float m_startX;
  float m_startY;
  float m_endX;
  float m_endY;
};

class JSRadialGradientShader : public JSGradientShader
{
public:
  JSRadialGradientShader(
      const ColorInt colors[],
      const float stops[],
      size_t count,
      float cx,
      float cy,
      float radius)
      : JSGradientShader(colors, stops, count)
      , m_centerX(cx)
      , m_centerY(cy)
      , m_radius(radius)
  {}

  void applyToPaint(const emscripten::val& jsPaint) const override
  {
    // renderer.js takes the radius as a second point on the circle. Matches
    // Canvas2DRadialGradientShader::passToJS in bindings_c2d.cpp.
    jsPaint.call<void>(
        "radialGradient",
        m_centerX,
        m_centerY,
        m_centerX + m_radius,
        m_centerY);
    applyStopsToPaint(jsPaint);
  }

private:
  float m_centerX;
  float m_centerY;
  float m_radius;
};

class JSAngularGradientShader : public JSGradientShader
{
public:
  JSAngularGradientShader(
      const ColorInt colors[],
      const float stops[],
      size_t count)
      : JSGradientShader(colors, stops, count)
  {}

  void applyToPaint(const emscripten::val& jsPaint) const override
  {
    jsPaint.call<void>("angularGradient");
    applyStopsToPaint(jsPaint);
  }
};

class JSRenderPath : public LITE_RTTI_OVERRIDE(RenderPath, JSRenderPath)
{
public:
  JSRenderPath(emscripten::val&& jsPath)
      : m_jsPath(std::forward<emscripten::val>(jsPath))
  {}

  // renderer.js's _drawPath/_clipPath capture the path in deferred draw-list
  // closures, so its deletion waits for the flush in
  // TestingWindowCanvas2D::endFrame().
  ~JSRenderPath() override { m_jsPath.call<void>("deleteLater"); }

  void rewind() override { m_jsPath.call<void>("rewind"); }

  void fillRule(FillRule value) override
  {
    m_jsPath.call<void>("fillRule", jsEnums().fillRule(value));
  }

  void moveTo(float x, float y) override
  {
    m_jsPath.call<void>("moveTo", x, y);
  }

  void lineTo(float x, float y) override
  {
    m_jsPath.call<void>("lineTo", x, y);
  }

  void cubicTo(float ox, float oy, float ix, float iy, float x, float y)
      override
  {
    m_jsPath.call<void>("cubicTo", ox, oy, ix, iy, x, y);
  }

  void close() override { m_jsPath.call<void>("close"); }

  void addRenderPath(const RenderPath* path, const Mat2D& transform) override
  {
    float xx = transform.xx();
    float xy = transform.xy();
    float yx = transform.yx();
    float yy = transform.yy();
    float tx = transform.tx();
    float ty = transform.ty();
    auto* jsPath = rive::lite_rtti_cast_or_assert<const JSRenderPath*>(path);
    m_jsPath.call<void>("addPath", jsPath->js(), xx, xy, yx, yy, tx, ty);
  }

  void addRawPath(const RawPath& path) override
  {
    const rive::Vec2D* pts = path.points().data();
    for (auto v : path.verbs())
    {
      switch ((rive::PathVerb)v)
      {
        case rive::PathVerb::move:
          move(*pts++);
          break;
        case rive::PathVerb::line:
          line(*pts++);
          break;
        case rive::PathVerb::cubic:
          cubic(pts[0], pts[1], pts[2]);
          pts += 3;
          break;
        case rive::PathVerb::close:
          close();
          break;
        default:
          assert(false); // unexpected verb
      }
    }
    assert(pts - path.points().data() == path.points().size());
  }

  emscripten::val& js() { return m_jsPath; }
  const emscripten::val& js() const { return m_jsPath; }

private:
  emscripten::val m_jsPath;
};

class JSRenderImage : public LITE_RTTI_OVERRIDE(RenderImage, JSRenderImage)
{
public:
  JSRenderImage(emscripten::val&& jsImage)
      : m_jsImage(std::forward<emscripten::val>(jsImage))
  {
    // On load, renderer.js calls size() on the RenderImage it created,
    // setting the dimensions on the wrapper in canvas_advanced's heap. This
    // is a separate rive::RenderImage with its own m_Width/m_Height, which
    // rive core reads, so copy them across.
    emscripten::val testUtils = canvasAdvancedModule()["Canvas2DTestUtilities"];
    m_Width = testUtils.call<int>("imageWidth", m_jsImage);
    m_Height = testUtils.call<int>("imageHeight", m_jsImage);
  }

  ~JSRenderImage() override { m_jsImage.call<void>("deleteLater"); }

  emscripten::val& js() { return m_jsImage; }
  const emscripten::val& js() const { return m_jsImage; }

private:
  emscripten::val m_jsImage;
};

class JSRenderPaint : public LITE_RTTI_OVERRIDE(RenderPaint, JSRenderPaint)
{
public:
  JSRenderPaint(emscripten::val&& jsPaint)
      : m_jsPaint(std::forward<emscripten::val>(jsPaint))
  {}

  ~JSRenderPaint() override { m_jsPaint.call<void>("deleteLater"); }

  void style(RenderPaintStyle style) override
  {
    m_jsPaint.call<void>("style", jsEnums().paintStyle(style));
  }

  void color(ColorInt value) override { m_jsPaint.call<void>("color", value); }

  void thickness(float value) override
  {
    m_jsPaint.call<void>("thickness", value);
  }

  void join(StrokeJoin value) override
  {
    m_jsPaint.call<void>("join", jsEnums().strokeJoin(value));
  }

  void cap(StrokeCap value) override
  {
    m_jsPaint.call<void>("cap", jsEnums().strokeCap(value));
  }

  void strokePosition(StrokePosition value) override
  {
    m_jsPaint.call<void>("strokePosition", jsEnums().strokePosition(value));
  }

  void feather(float value) override { m_jsPaint.call<void>("feather", value); }

  void blendMode(BlendMode value) override
  {
    m_jsPaint.call<void>("blendMode", jsEnums().blendMode(value));
  }

  void shader(rcp<RenderShader> shader) override
  {
    if (shader == nullptr)
    {
      m_jsPaint.call<void>("clearGradient");
      return;
    }

    rive::lite_rtti_cast_or_assert<JSGradientShader*>(shader.get())
        ->applyToPaint(m_jsPaint);
  }

  void shaderTransform(const Mat2D& transform) override
  {
    m_jsPaint.call<void>(
        "gradientTransform",
        transform.xx(),
        transform.xy(),
        transform.yx(),
        transform.yy(),
        transform.tx(),
        transform.ty());
  }

  void invalidateStroke() override {}

  void modulatedImage(
      const RenderImage* image,
      ImageSampler sampler,
      const Mat2D& xform) override
  {
    auto* jsImage = rive::lite_rtti_cast_or_assert<const JSRenderImage*>(image);
    m_jsPaint.call<void>(
        "modulatedImage",
        jsImage->js(),
        jsEnums().imageFilter(sampler.filter),
        jsEnums().imageWrap(sampler.wrapX),
        jsEnums().imageWrap(sampler.wrapY),
        xform[0],
        xform[1],
        xform[2],
        xform[3],
        xform[4],
        xform[5]);
  }

  emscripten::val& js() { return m_jsPaint; }
  const emscripten::val& js() const { return m_jsPaint; }

private:
  emscripten::val m_jsPaint;
};

class JSRenderFactory : public rive::Factory
{
public:
  JSRenderFactory() : m_jsFactory(canvasAdvancedModule()["renderFactory"]) {}

  rcp<RenderBuffer> makeRenderBuffer(
      RenderBufferType type,
      RenderBufferFlags flags,
      size_t sizeInBytes) override
  {
    // These never cross the module boundary: rive core maps and fills them
    // here, and JSRenderer::drawImageMesh() copies the contents over when
    // it hands off.
    return make_rcp<DataRenderBuffer>(type, flags, sizeInBytes);
  }

  rcp<RenderShader> makeLinearGradient(
      float sx,
      float sy,
      float ex,
      float ey,
      const ColorInt colors[],
      const float stops[],
      size_t count) override
  {
    return rcp<RenderShader>(
        new JSLinearGradientShader(colors, stops, count, sx, sy, ex, ey));
  }

  rcp<RenderShader> makeRadialGradient(
      float cx,
      float cy,
      float radius,
      const ColorInt colors[],
      const float stops[],
      size_t count) override
  {
    return rcp<RenderShader>(
        new JSRadialGradientShader(colors, stops, count, cx, cy, radius));
  }

  rcp<RenderShader> makeAngularGradient(
      const ColorInt colors[],
      const float stops[],
      size_t count) override
  {
    return rcp<RenderShader>(new JSAngularGradientShader(colors, stops, count));
  }

  rcp<RenderPath> makeRenderPath(RawPath& rawPath, FillRule fillRule) override
  {
    rcp<RenderPath> renderPath = makeEmptyRenderPath();
    renderPath->addRawPath(rawPath);
    renderPath->fillRule(fillRule);
    return renderPath;
  }

  rcp<RenderPath> makeEmptyRenderPath() override
  {
    return make_rcp<JSRenderPath>(
        m_jsFactory.call<emscripten::val>("makeRenderPath"));
  }

  rcp<RenderPaint> makeRenderPaint() override
  {
    return make_rcp<JSRenderPaint>(
        m_jsFactory.call<emscripten::val>("makeRenderPaint"));
  }

  rcp<RenderImage> decodeImage(Span<const uint8_t> bytes) override
  {
    if (bytes.empty())
    {
      return nullptr;
    }

    // Blocks until the <img> load event fires.
    return make_rcp<JSRenderImage>(
        emscripten::val::take_ownership(testingWindowCanvas2dDecodeImage(
            bytes.data(),
            static_cast<int>(bytes.size()))));
  }

private:
  emscripten::val m_jsFactory;
};

class JSRenderer : public rive::Renderer
{
public:
  JSRenderer()
      : m_jsRenderer(canvasAdvancedModule().call<emscripten::val>(
            "makeRenderer",
            emscripten::val::global("document")
                .call<emscripten::val>(
                    "getElementById",
                    std::string("canvas"))))
  {}

  // renderer.js holds this renderer in _pendingCanvasRenderers until the draw
  // list is flushed.
  ~JSRenderer() override { m_jsRenderer.call<void>("deleteLater"); }

  void beginFrame(bool clear) { m_jsRenderer.call<void>("beginFrame", clear); }

  void save() override { m_jsRenderer.call<void>("save"); }
  void restore() override { m_jsRenderer.call<void>("restore"); }

  void transform(const Mat2D& matrix) override
  {
    m_jsRenderer.call<void>(
        "transform",
        matrix.xx(),
        matrix.xy(),
        matrix.yx(),
        matrix.yy(),
        matrix.tx(),
        matrix.ty());
  }

  void drawPath(RenderPath* path, RenderPaint* paint) override
  {
    auto* jsPath = rive::lite_rtti_cast_or_assert<JSRenderPath*>(path);
    auto* jsPaint = rive::lite_rtti_cast_or_assert<JSRenderPaint*>(paint);
    m_jsRenderer.call<void>("_drawPath", jsPath->js(), jsPaint->js());
  }

  void clipPath(RenderPath* path) override
  {
    auto* jsPath = rive::lite_rtti_cast_or_assert<JSRenderPath*>(path);
    m_jsRenderer.call<void>("_clipPath", jsPath->js());
  }

  void drawImage(
      const RenderImage* image,
      ImageSampler sampler,
      BlendMode blendMode,
      float opacity) override
  {
    auto* jsImage = rive::lite_rtti_cast_or_assert<const JSRenderImage*>(image);
    m_jsRenderer.call<void>(
        "_drawRiveImage",
        jsImage->js(),
        jsEnums().blendMode(blendMode),
        opacity);
  }

  void drawImageMesh(
      const RenderImage* image,
      ImageSampler sampler,
      rcp<RenderBuffer> vertices_f32,
      rcp<RenderBuffer> uvCoords_f32,
      rcp<RenderBuffer> indices_u16,
      uint32_t vertexCount,
      uint32_t indexCount,
      BlendMode blendMode,
      float opacity) override
  {
    auto* vtx = rive::lite_rtti_cast_or_assert<rive::DataRenderBuffer*>(
        vertices_f32.get());
    auto* uv = rive::lite_rtti_cast_or_assert<rive::DataRenderBuffer*>(
        uvCoords_f32.get());
    auto* indices = rive::lite_rtti_cast_or_assert<rive::DataRenderBuffer*>(
        indices_u16.get());

    uint32_t f32Count = vertexCount * 2;
    assert(vtx->sizeInBytes() == f32Count * sizeof(float));
    assert(uv->sizeInBytes() == f32Count * sizeof(float));
    assert(indices->sizeInBytes() == indexCount * sizeof(uint16_t));

    if (f32Count == 0 || indexCount == 0)
    {
      return;
    }

    // This hands off to the C++ side of canvas_advanced so that the real
    // Canvas2DRendererWrapper::drawImageMesh() runs. It owns the mesh
    // bounding box computation and the atlas packing, which the harness
    // would otherwise duplicate here, leaving them untested.
    //
    // The typed_memory_views below are over this module's heap.
    // canvas_advanced can read them because a TypedArray is a plain JS
    // object, whichever ArrayBuffer it wraps, and it copies into its own
    // DataRenderBuffers. Nothing between here and the call allocates, so
    // this module's memory cannot grow and detach them in the meantime.
    auto* jsImage = rive::lite_rtti_cast_or_assert<const JSRenderImage*>(image);
    canvasAdvancedModule()["Canvas2DTestUtilities"].call<void>(
        "drawImageMesh",
        m_jsRenderer,
        jsImage->js(),
        emscripten::val{emscripten::typed_memory_view(f32Count, vtx->f32s())},
        emscripten::val{emscripten::typed_memory_view(f32Count, uv->f32s())},
        emscripten::val{
            emscripten::typed_memory_view(indexCount, indices->u16s())},
        jsEnums().blendMode(blendMode),
        opacity);
  }

  void modulateOpacity(float opacity) override
  {
    m_jsRenderer.call<void>("modulateOpacity", opacity);
  }

private:
  emscripten::val m_jsRenderer;
};

class TestingWindowCanvas2D : public TestingWindow
{
public:
  TestingWindowCanvas2D()
  {
    testingWindowCanvas2dImportCanvasAdvanced();

    int w, h;
    emscripten_get_canvas_element_size("#canvas", &w, &h);
    m_width = w;
    m_height = h;

    m_factory = std::make_unique<JSRenderFactory>();
  }

  rive::Factory* factory() override { return m_factory.get(); }

  void resize(int width, int height) override
  {
    if (m_width != width || m_height != height)
    {
      TestingWindow::resize(width, height);
      emscripten_set_canvas_element_size("#canvas", width, height);
    }
  }

  std::unique_ptr<rive::Renderer> beginFrame(
      const FrameOptions& options) override
  {
    m_frameName = options.name != nullptr ? options.name : "<frame>";
    canvasAdvancedModule()["Canvas2DTestUtilities"].call<void>(
        "setMaxCanvasAtlasSize",
        options.maxCanvasAtlasSize);

    if (options.doClear)
    {
      testingWindowCanvas2dResetCanvas(options.clearColor);
    }

    auto renderer = std::make_unique<JSRenderer>();
    renderer->beginFrame(false);

    return renderer;
  }

  void endFrame(std::vector<uint8_t>* pixelData) override
  {
    // Flush commands so that we can read pixel data from the canvas.
    canvasAdvancedModule().call<void>("resolveAnimationFrame");

    // The flush should have executed and released data associated with all
    // pending draws.
    if (int pending = canvasAdvancedModule()["Canvas2DTestUtilities"].call<int>(
            "pendingAtlasReleaseCount"))
    {
      fprintf(
          stderr,
          "%s: %i delegated draw(s) were never released\n",
          m_frameName.c_str(),
          pending);
      abort();
    }

    // The deferred draw list has run, so nothing on the JS side still holds
    // the objects the shims above queued with deleteLater(). embind
    // attaches no finalizer to raw pointer handles, so without this call
    // every path, paint and renderer accumulates in canvas_advanced's heap
    // for the whole run.
    canvasAdvancedModule().call<void>("flushPendingDeletes");

    if (!pixelData)
    {
      return;
    }

    pixelData->resize(m_width * m_height * 4);
    if (!testingWindowCanvas2dGetCanvasPixels(
            pixelData->data(),
            m_width,
            m_height))
    {
      printf("Canvas size mismatch, read failed\n");
      pixelData->assign(pixelData->size(), 0);
      return;
    }

    // getImageData() hands back unpremultiplied RGBA. Multiply by alpha to
    // match the other backends.
    for (size_t i = 0; i < pixelData->size(); i += 4)
    {
      uint32_t a = (*pixelData)[i + 3];
      for (size_t c = 0; c < 3; ++c)
      {
        (*pixelData)[i + c] = static_cast<uint8_t>(
            ((*pixelData)[i + c] * a + 127) / 255);
      }
    }
  }

private:
  std::unique_ptr<JSRenderFactory> m_factory;
  std::string m_frameName;
};
}; // namespace rive::gpu

TestingWindow* TestingWindow::MakeCanvas2D()
{
  return new rive::gpu::TestingWindowCanvas2D();
}

#endif
