/*
 * Copyright 2026 Rive
 */

#include "rive/renderer/cmd/deferred_render_factory.hpp"
#include "rive/renderer/cmd/render_replay.hpp"

// Out of line home for the large deferred stream bodies, so every TU that
// touches the deferred headers does not recompile them.
namespace rive::cmd
{

bool sniffImageSize(Span<const uint8_t> b, int& w, int& h)
{
    const uint8_t* d = b.data();
    size_t n = b.size();
    auto be32 = [&](size_t i) {
        return (d[i] << 24) | (d[i + 1] << 16) | (d[i + 2] << 8) | d[i + 3];
    };
    // PNG: 8-byte sig, then IHDR with width/height as big-endian u32 at 16/20.
    if (n >= 24 && d[0] == 0x89 && d[1] == 'P' && d[2] == 'N' && d[3] == 'G')
    {
        w = static_cast<int>(be32(16));
        h = static_cast<int>(be32(20));
        return true;
    }
    // GIF: "GIF87a"/"GIF89a", then width/height little-endian u16 at 6/8.
    if (n >= 10 && d[0] == 'G' && d[1] == 'I' && d[2] == 'F')
    {
        w = d[6] | (d[7] << 8);
        h = d[8] | (d[9] << 8);
        return true;
    }
    // WEBP: RIFF....WEBP; VP8 / VP8L / VP8X carry dims at known offsets.
    if (n >= 30 && d[0] == 'R' && d[1] == 'I' && d[2] == 'F' && d[3] == 'F' &&
        d[8] == 'W' && d[9] == 'E' && d[10] == 'B' && d[11] == 'P')
    {
        if (d[12] == 'V' && d[13] == 'P' && d[14] == '8' && d[15] == ' ')
        {
            w = (d[26] | (d[27] << 8)) & 0x3fff;
            h = (d[28] | (d[29] << 8)) & 0x3fff;
            return true;
        }
        if (d[12] == 'V' && d[13] == 'P' && d[14] == '8' && d[15] == 'L')
        {
            uint32_t bits =
                d[21] | (d[22] << 8) | (d[23] << 16) | (d[24] << 24);
            w = static_cast<int>((bits & 0x3fff) + 1);
            h = static_cast<int>(((bits >> 14) & 0x3fff) + 1);
            return true;
        }
        if (d[12] == 'V' && d[13] == 'P' && d[14] == '8' && d[15] == 'X')
        {
            w = (d[24] | (d[25] << 8) | (d[26] << 16)) + 1;
            h = (d[27] | (d[28] << 8) | (d[29] << 16)) + 1;
            return true;
        }
    }
    // JPEG: walk markers to an SOF (0xC0..0xCF, excluding non-SOF) for dims.
    if (n >= 4 && d[0] == 0xff && d[1] == 0xd8)
    {
        size_t i = 2;
        while (i + 9 < n)
        {
            if (d[i] != 0xff)
            {
                i++;
                continue;
            }
            uint8_t marker = d[i + 1];
            // SOF0..SOF15 carry dims; skip DHT(C4)/DAA(C8)/DAC(CC) which don't.
            if (marker >= 0xc0 && marker <= 0xcf && marker != 0xc4 &&
                marker != 0xc8 && marker != 0xcc)
            {
                h = (d[i + 5] << 8) | d[i + 6];
                w = (d[i + 7] << 8) | d[i + 8];
                return true;
            }
            uint32_t seg = (d[i + 2] << 8) | d[i + 3];
            i += 2 + seg;
        }
    }
    return false;
}

void replayRenderCommands(Factory* factory,
                          Renderer* renderer,
                          Span<const uint8_t> commands,
                          Span<const uint8_t> blobs,
                          ResourceTable& table,
                          const ReplayHooks& hooks)
{
    auto& paths = table.paths;
    auto& paints = table.paints;
    auto& shaders = table.shaders;
    auto& images = table.images;
    auto& buffers = table.buffers;
    auto& meshInstances = table.imageMeshInstances;

    auto filterAllows = [](ReplayFilter f, RenderCmd c) {
        if (f == ReplayFilter::all)
        {
            return true;
        }
        switch (c)
        {
            case RenderCmd::save:
            case RenderCmd::restore:
            case RenderCmd::transform:
            case RenderCmd::drawPath:
            case RenderCmd::clipPath:
            case RenderCmd::clipStroke:
            case RenderCmd::drawImage:
            case RenderCmd::drawImageMesh:
            case RenderCmd::drawImageMeshInstanced:
            case RenderCmd::applyLayerMask:
            case RenderCmd::modulateOpacity:
            case RenderCmd::modulateColor:
            case RenderCmd::canvasContentBegin:
            case RenderCmd::canvasContentEnd:
                return f == ReplayFilter::draws;
            case RenderCmd::destroyResource:
                return f == ReplayFilter::destroys;
            default:
                return f == ReplayFilter::resources;
        }
    };

    RenderCommandReader reader(commands, blobs);
    auto path = [&](RenderHandle h) -> RenderPath* { return paths.get(h); };
    auto paint = [&](RenderHandle h) -> RenderPaint* { return paints.get(h); };
    auto image = [&](RenderHandle h) -> RenderImage* { return images.get(h); };
    auto sampler = [](uint8_t wx, uint8_t wy, uint8_t f) {
        return ImageSampler{static_cast<ImageWrap>(wx),
                            static_cast<ImageWrap>(wy),
                            static_cast<ImageFilter>(f)};
    };

    // Draws route into cur: the screen by default, or the active canvas
    // between content brackets. Null drops the draw.
    Renderer* cur = renderer;

    uint8_t type;
    uint8_t prevType = 255;
    size_t prevPos = 0;
    while (reader.next(type))
    {
        if (type > static_cast<uint8_t>(RenderCmd::lastRenderCmd))
        {
            // Unknown opcode: its payload was not consumed, so every later
            // read would desync. Stop.
            fprintf(stderr,
                    "rive replay ABORT: opcode %u at byte %zu of %zu, last "
                    "good opcode %u at byte %zu\n",
                    type,
                    reader.position() - 1,
                    commands.size(),
                    prevType,
                    prevPos);
            assert(false);
            break;
        }
        prevType = type;
        prevPos = reader.position() - 1;
        const auto cmd = static_cast<RenderCmd>(type);
        if (!filterAllows(hooks.filter, cmd))
        {
            reader.skip(payloadSizeOf(cmd));
            continue;
        }
        switch (cmd)
        {
            case RenderCmd::makePath:
            {
                auto c = reader.read<MakePathPOD>();
                RawPath raw = rebuildRawPath(
                    reader.blobAt(c.blobOffset,
                                  c.verbCount *
                                      static_cast<uint32_t>(sizeof(PathVerb))),
                    reader.blobAt(c.pointsOffset,
                                  c.pointCount *
                                      static_cast<uint32_t>(sizeof(Vec2D))));
                paths.set(
                    c.id,
                    factory->makeRenderPath(raw,
                                            static_cast<FillRule>(c.fillRule)),
                    c.generation);
                if (c.id >= table.pathFillRules.size())
                {
                    table.pathFillRules.resize(c.id + 1);
                }
                table.pathFillRules[c.id] = c.fillRule;
                break;
            }
            case RenderCmd::makeEmptyPath:
            {
                auto c = reader.read<MakeIdPOD>();
                paths.set(c.id, factory->makeEmptyRenderPath(), c.generation);
                if (c.id >= table.pathFillRules.size())
                {
                    table.pathFillRules.resize(c.id + 1);
                }
                table.pathFillRules[c.id] = 0;
                break;
            }
            case RenderCmd::makePaint:
            {
                auto c = reader.read<MakeIdPOD>();
                paints.set(c.id, factory->makeRenderPaint(), c.generation);
                if (c.id >= table.paintShadows.size())
                {
                    table.paintShadows.resize(c.id + 1);
                }
                table.paintShadows[c.id] = PaintShadow{};
                break;
            }
            case RenderCmd::makeLinearGradient:
            {
                auto c = reader.read<LinearGradientPOD>();
                const ColorInt* colors = reinterpret_cast<const ColorInt*>(
                    reader
                        .blobAt(c.blobOffset,
                                c.count *
                                    static_cast<uint32_t>(sizeof(ColorInt)))
                        .data());
                const float* stops = reinterpret_cast<const float*>(
                    reader
                        .blobAt(c.stopsOffset,
                                c.count * static_cast<uint32_t>(sizeof(float)))
                        .data());
                if (colors == nullptr || stops == nullptr)
                {
                    break; // blob out of range (corrupt stream)
                }
                shaders.set(c.id,
                            factory->makeLinearGradient(c.sx,
                                                        c.sy,
                                                        c.ex,
                                                        c.ey,
                                                        colors,
                                                        stops,
                                                        c.count),
                            c.generation);
                break;
            }
            case RenderCmd::makeRadialGradient:
            {
                auto c = reader.read<RadialGradientPOD>();
                const ColorInt* colors = reinterpret_cast<const ColorInt*>(
                    reader
                        .blobAt(c.blobOffset,
                                c.count *
                                    static_cast<uint32_t>(sizeof(ColorInt)))
                        .data());
                const float* stops = reinterpret_cast<const float*>(
                    reader
                        .blobAt(c.stopsOffset,
                                c.count * static_cast<uint32_t>(sizeof(float)))
                        .data());
                if (colors == nullptr || stops == nullptr)
                {
                    break; // blob out of range (corrupt stream)
                }
                shaders.set(c.id,
                            factory->makeRadialGradient(c.cx,
                                                        c.cy,
                                                        c.radius,
                                                        colors,
                                                        stops,
                                                        c.count),
                            c.generation);
                break;
            }
            case RenderCmd::decodeImage:
            {
                auto c = reader.read<DecodeImagePOD>();
                images.set(c.id,
                           factory->decodeImage(
                               reader.blobAt(c.blobOffset, c.byteCount)),
                           c.generation);
                break;
            }
            case RenderCmd::makeBuffer:
            {
                auto c = reader.read<MakeBufferPOD>();
                buffers.set(c.id,
                            factory->makeRenderBuffer(
                                static_cast<RenderBufferType>(c.bufferType),
                                static_cast<RenderBufferFlags>(c.flags),
                                c.sizeInBytes),
                            c.generation);
                if (c.id >= table.bufferShadows.size())
                {
                    table.bufferShadows.resize(c.id + 1);
                }
                table.bufferShadows[c.id] = {static_cast<uint8_t>(c.bufferType),
                                             static_cast<uint16_t>(c.flags),
                                             c.sizeInBytes};
                break;
            }
            case RenderCmd::makeImageMeshInstances:
            {
                auto c = reader.read<MakeImageMeshInstancesPOD>();
                meshInstances.set(c.id,
                                  factory->makeImageMeshInstances(c.count),
                                  c.generation);
                break;
            }
            case RenderCmd::imageMeshInstancesData:
            {
                auto c = reader.read<ImageMeshInstancesDataPOD>();
                Span<const uint8_t> src =
                    reader.blobAt(c.blobOffset,
                                  c.count * static_cast<uint32_t>(
                                                sizeof(ImageMeshInstanceData)));
                if (auto* mi = meshInstances.get(c.id))
                {
                    if (src.size() == c.count * sizeof(ImageMeshInstanceData))
                    {
                        Span<ImageMeshInstanceData> dst = mi->edit(c.count);
                        std::memcpy(dst.data(), src.data(), src.size_bytes());
                        mi->endEdit();
                    }
                }
                break;
            }
            case RenderCmd::bufferData:
            {
                auto c = reader.read<BufferDataPOD>();
                Span<const uint8_t> src = reader.blobAt(c.blobOffset, c.size);
                if (auto* b = buffers.get(c.buffer))
                {
                    if (src.size() == c.size)
                    {
                        void* dst = b->map();
                        if (dst)
                        {
                            std::memcpy(dst, src.data(), c.size);
                        }
                        b->unmap();
                    }
                }
                break;
            }
            case RenderCmd::destroyResource:
            {
                auto c = reader.read<DestroyResourcePOD>();
                table.destroy(static_cast<ResourceKind>(c.kind),
                              c.id,
                              c.generation);
                break;
            }
            case RenderCmd::resourceNewVersion:
            {
                // A drawn resource was mutated again: alias the outgoing
                // version for the draws that pinned it and continue on a
                // fresh object carrying the shadowed state.
                auto c = reader.read<ResourceVersionPOD>();
                switch (static_cast<ResourceKind>(c.kind))
                {
                    case ResourceKind::paint:
                    {
                        auto fresh = factory->makeRenderPaint();
                        if (fresh != nullptr &&
                            c.id < table.paintShadows.size())
                        {
                            const PaintShadow& sh = table.paintShadows[c.id];
                            fresh->style(
                                static_cast<RenderPaintStyle>(sh.style));
                            fresh->color(sh.color);
                            fresh->thickness(sh.thickness);
                            fresh->join(static_cast<StrokeJoin>(sh.join));
                            fresh->cap(static_cast<StrokeCap>(sh.cap));
                            fresh->strokePosition(
                                static_cast<StrokePosition>(sh.strokePosition));
                            fresh->feather(sh.feather);
                            fresh->additiveness(sh.additiveness);
                            fresh->blendMode(
                                static_cast<BlendMode>(sh.blendMode));
                            if (sh.shader != kInvalidRenderHandle)
                            {
                                fresh->shader(shaders.shared(sh.shader));
                            }
                            if (sh.image != kInvalidRenderHandle)
                            {
                                RenderImage* im =
                                    (sh.image & kCanvasHandleFlag)
                                        ? (hooks.canvasImage
                                               ? hooks.canvasImage(
                                                     sh.image &
                                                     kCanvasHandleMask)
                                               : nullptr)
                                        : images.get(sh.image);
                                fresh->modulatedImage(
                                    im,
                                    ImageSampler{
                                        static_cast<ImageWrap>(sh.imageWrapX),
                                        static_cast<ImageWrap>(sh.imageWrapY),
                                        static_cast<ImageFilter>(
                                            sh.imageFilter)},
                                    Mat2D(sh.imageXX,
                                          sh.imageXY,
                                          sh.imageYX,
                                          sh.imageYY,
                                          sh.imageTX,
                                          sh.imageTY));
                            }
                        }
                        paints.newVersion(c.id, c.version, std::move(fresh));
                        break;
                    }
                    case ResourceKind::path:
                    {
                        // Seed from the outgoing version so a non rewind
                        // mutation appends onto prior geometry; a rewind bump
                        // clears the seed via its own recorded command.
                        auto fresh = factory->makeEmptyRenderPath();
                        if (fresh != nullptr)
                        {
                            if (auto* outgoing = paths.get(c.id))
                            {
                                fresh->addRenderPath(outgoing, Mat2D());
                            }
                            if (c.id < table.pathFillRules.size())
                            {
                                fresh->fillRule(static_cast<FillRule>(
                                    table.pathFillRules[c.id]));
                            }
                        }
                        paths.newVersion(c.id, c.version, std::move(fresh));
                        break;
                    }
                    case ResourceKind::buffer:
                    {
                        rcp<RenderBuffer> fresh;
                        if (c.id < table.bufferShadows.size())
                        {
                            const BufferShadow& sh = table.bufferShadows[c.id];
                            fresh = factory->makeRenderBuffer(
                                static_cast<RenderBufferType>(sh.type),
                                static_cast<RenderBufferFlags>(sh.flags),
                                sh.size);
                        }
                        buffers.newVersion(c.id, c.version, std::move(fresh));
                        break;
                    }
                    case ResourceKind::imageMeshInstances:
                    {
                        meshInstances.newVersion(
                            c.id,
                            c.version,
                            factory->makeImageMeshInstances(0));
                        break;
                    }
                    default:
                        break; // shaders and images never mutate
                }
                break;
            }

            case RenderCmd::pathRewind:
            {
                auto c = reader.read<ResIdPOD>();
                if (auto* p = path(c.id))
                {
                    p->rewind();
                }
                break;
            }
            case RenderCmd::pathFillRule:
            {
                auto c = reader.read<PathFillRulePOD>();
                if (auto* p = path(c.path))
                {
                    p->fillRule(static_cast<FillRule>(c.fillRule));
                    table.pathFillRules[c.path] = c.fillRule;
                }
                break;
            }
            case RenderCmd::pathAddRawPath:
            {
                auto c = reader.read<PathRawPOD>();
                RawPath raw = rebuildRawPath(
                    reader.blobAt(c.blobOffset,
                                  c.verbCount *
                                      static_cast<uint32_t>(sizeof(PathVerb))),
                    reader.blobAt(c.pointsOffset,
                                  c.pointCount *
                                      static_cast<uint32_t>(sizeof(Vec2D))));
                if (auto* p = path(c.path))
                {
                    p->addRawPath(raw);
                }
                break;
            }
            case RenderCmd::pathAddRenderPath:
            {
                auto c = reader.read<PathAddPathPOD>();
                RenderPath* src = paths.get(c.src);
                if (auto* p = path(c.path))
                {
                    if (src)
                        p->addRenderPath(
                            src,
                            Mat2D(c.xx, c.xy, c.yx, c.yy, c.tx, c.ty));
                }
                break;
            }

            case RenderCmd::paintStyle:
            {
                auto c = reader.read<PaintU8POD>();
                if (auto* pt = paint(c.paint))
                {
                    pt->style(static_cast<RenderPaintStyle>(c.value));
                    table.paintShadows[c.paint].style = c.value;
                }
                break;
            }
            case RenderCmd::paintColor:
            {
                auto c = reader.read<PaintColorPOD>();
                if (auto* pt = paint(c.paint))
                {
                    pt->color(c.color);
                    table.paintShadows[c.paint].color = c.color;
                }
                break;
            }
            case RenderCmd::paintThickness:
            {
                auto c = reader.read<PaintFloatPOD>();
                if (auto* pt = paint(c.paint))
                {
                    pt->thickness(c.value);
                    table.paintShadows[c.paint].thickness = c.value;
                }
                break;
            }
            case RenderCmd::paintJoin:
            {
                auto c = reader.read<PaintU8POD>();
                if (auto* pt = paint(c.paint))
                {
                    pt->join(static_cast<StrokeJoin>(c.value));
                    table.paintShadows[c.paint].join = c.value;
                }
                break;
            }
            case RenderCmd::paintCap:
            {
                auto c = reader.read<PaintU8POD>();
                if (auto* pt = paint(c.paint))
                {
                    pt->cap(static_cast<StrokeCap>(c.value));
                    table.paintShadows[c.paint].cap = c.value;
                }
                break;
            }
            case RenderCmd::paintStrokePosition:
            {
                auto c = reader.read<PaintU8POD>();
                if (auto* pt = paint(c.paint))
                {
                    pt->strokePosition(static_cast<StrokePosition>(c.value));
                    table.paintShadows[c.paint].strokePosition = c.value;
                }
                break;
            }
            case RenderCmd::paintFeather:
            {
                auto c = reader.read<PaintFloatPOD>();
                if (auto* pt = paint(c.paint))
                {
                    pt->feather(c.value);
                    table.paintShadows[c.paint].feather = c.value;
                }
                break;
            }
            case RenderCmd::paintAdditiveness:
            {
                auto c = reader.read<PaintFloatPOD>();
                if (auto* pt = paint(c.paint))
                {
                    pt->additiveness(c.value);
                    table.paintShadows[c.paint].additiveness = c.value;
                }
                break;
            }
            case RenderCmd::paintBlendMode:
            {
                auto c = reader.read<PaintU8POD>();
                if (auto* pt = paint(c.paint))
                {
                    pt->blendMode(static_cast<BlendMode>(c.value));
                    table.paintShadows[c.paint].blendMode = c.value;
                }
                break;
            }
            case RenderCmd::paintShader:
            {
                auto c = reader.read<PaintShaderPOD>();
                if (auto* pt = paint(c.paint))
                {
                    pt->shader(shaders.shared(c.shader));
                    table.paintShadows[c.paint].shader = c.shader;
                }
                break;
            }
            case RenderCmd::paintModulatedImage:
            {
                auto c = reader.read<PaintModulatedImagePOD>();
                if (auto* pt = paint(c.paint))
                {
                    RenderImage* im =
                        c.image == kInvalidRenderHandle ? nullptr
                        : (c.image & kCanvasHandleFlag)
                            ? (hooks.canvasImage
                                   ? hooks.canvasImage(c.image &
                                                       kCanvasHandleMask)
                                   : nullptr)
                            : image(c.image);
                    pt->modulatedImage(
                        im,
                        sampler(c.wrapX, c.wrapY, c.filter),
                        Mat2D(c.xx, c.xy, c.yx, c.yy, c.tx, c.ty));
                    PaintShadow& sh = table.paintShadows[c.paint];
                    sh.image = c.image;
                    sh.imageWrapX = c.wrapX;
                    sh.imageWrapY = c.wrapY;
                    sh.imageFilter = c.filter;
                    sh.imageXX = c.xx;
                    sh.imageXY = c.xy;
                    sh.imageYX = c.yx;
                    sh.imageYY = c.yy;
                    sh.imageTX = c.tx;
                    sh.imageTY = c.ty;
                }
                break;
            }
            case RenderCmd::paintInvalidateStroke:
            {
                auto c = reader.read<ResIdPOD>();
                if (auto* pt = paint(c.id))
                {
                    pt->invalidateStroke();
                }
                break;
            }

            case RenderCmd::save:
                if (cur)
                {
                    cur->save();
                }
                break;
            case RenderCmd::restore:
                if (cur)
                {
                    cur->restore();
                }
                break;
            case RenderCmd::transform:
            {
                auto c = reader.read<TransformPOD>();
                if (cur)
                {
                    cur->transform(Mat2D(c.xx, c.xy, c.yx, c.yy, c.tx, c.ty));
                }
                break;
            }
            case RenderCmd::drawPath:
            {
                auto c = reader.read<DrawPathPOD>();
                RenderPath* p = paths.get(c.path, c.pathVersion);
                RenderPaint* pt = paints.get(c.paint, c.paintVersion);
                if (cur && p && pt)
                {
                    cur->drawPath(p, pt);
                }
                else if (cur != nullptr && hooks.stats != nullptr)
                {
                    hooks.stats->droppedDraws = hooks.stats->droppedDraws + 1;
                    replay_detail::logDroppedDraw(type, c.path, c.paint);
                }
                break;
            }
            case RenderCmd::clipPath:
            {
                auto c = reader.read<ClipPathPOD>();
                if (cur)
                {
                    if (auto* p = paths.get(c.path, c.version))
                        cur->clipPath(p);
                }
                break;
            }
            case RenderCmd::clipStroke:
            {
                auto c = reader.read<ClipStrokePOD>();
                if (cur)
                {
                    if (auto* p = paths.get(c.path, c.version))
                        cur->clipStroke(
                            p,
                            {
                                .thickness = c.thickness,
                                .join = StrokeJoin(c.join),
                                .cap = StrokeCap(c.cap),
                                .position = StrokePosition(c.position),
                            });
                }
                break;
            }

            case RenderCmd::drawImage:
            {
                auto c = reader.read<DrawImagePOD>();
                RenderImage* im =
                    (c.image & kCanvasHandleFlag)
                        ? (hooks.canvasImage
                               ? hooks.canvasImage(c.image & kCanvasHandleMask)
                               : nullptr)
                        : image(c.image);
                if (cur && im)
                {
                    cur->drawImage(im,
                                   sampler(c.wrapX, c.wrapY, c.filter),
                                   static_cast<BlendMode>(c.blendMode),
                                   c.opacity,
                                   c.additiveness);
                }
                else if (cur != nullptr && hooks.stats != nullptr)
                {
                    hooks.stats->droppedDraws = hooks.stats->droppedDraws + 1;
                    replay_detail::logDroppedDraw(type, c.image, 0);
                }
                break;
            }
            case RenderCmd::applyLayerMask:
            {
                auto c = reader.read<ApplyLayerMaskPOD>();
                // The mask is nearly always a canvas image (layer masking
                // rasterizes its coverage into one), so the canvas hook is the
                // expected path here rather than the exception.
                RenderImage* im =
                    (c.mask & kCanvasHandleFlag)
                        ? (hooks.canvasImage
                               ? hooks.canvasImage(c.mask & kCanvasHandleMask)
                               : nullptr)
                        : image(c.mask);
                if (cur && im)
                {
                    cur->applyLayerMask(im,
                                        sampler(c.wrapX, c.wrapY, c.filter),
                                        static_cast<LayerMaskMode>(c.mode));
                }
                else if (cur != nullptr && hooks.stats != nullptr)
                {
                    hooks.stats->droppedDraws = hooks.stats->droppedDraws + 1;
                    replay_detail::logDroppedDraw(type, c.mask, 0);
                }
                break;
            }
            case RenderCmd::drawImageMesh:
            {
                auto c = reader.read<DrawImageMeshPOD>();
                RenderImage* im =
                    (c.image & kCanvasHandleFlag)
                        ? (hooks.canvasImage
                               ? hooks.canvasImage(c.image & kCanvasHandleMask)
                               : nullptr)
                        : image(c.image);
                rcp<RenderBuffer> vb =
                    buffers.shared(c.vertices, c.vertexVersion);
                rcp<RenderBuffer> uv = buffers.shared(c.uvCoords, c.uvVersion);
                rcp<RenderBuffer> ib =
                    buffers.shared(c.indices, c.indexVersion);
                if (cur && im && vb && uv && ib)
                {
                    cur->drawImageMesh(im,
                                       sampler(c.wrapX, c.wrapY, c.filter),
                                       vb,
                                       uv,
                                       ib,
                                       c.vertexCount,
                                       c.indexCount,
                                       static_cast<BlendMode>(c.blendMode),
                                       c.opacity,
                                       c.additiveness);
                }
                else if (cur != nullptr && hooks.stats != nullptr)
                {
                    hooks.stats->droppedDraws = hooks.stats->droppedDraws + 1;
                    replay_detail::logDroppedDraw(type, c.image, 0);
                }
                break;
            }
            case RenderCmd::drawImageMeshInstanced:
            {
                auto c = reader.read<DrawImageMeshInstancedPOD>();
                RenderImage* im =
                    (c.image & kCanvasHandleFlag)
                        ? (hooks.canvasImage
                               ? hooks.canvasImage(c.image & kCanvasHandleMask)
                               : nullptr)
                        : image(c.image);
                rcp<RenderBuffer> vb =
                    buffers.shared(c.vertices, c.vertexVersion);
                rcp<RenderBuffer> uv = buffers.shared(c.uvCoords, c.uvVersion);
                rcp<RenderBuffer> ib =
                    buffers.shared(c.indices, c.indexVersion);
                rcp<ImageMeshInstances> mi =
                    meshInstances.shared(c.instances, c.instancesVersion);
                if (cur && im && vb && uv && ib && mi)
                {
                    cur->drawImageMeshInstanced(
                        im,
                        sampler(c.wrapX, c.wrapY, c.filter),
                        vb,
                        uv,
                        ib,
                        c.vertexCount,
                        c.indexCount,
                        std::move(mi));
                }
                else if (cur != nullptr && hooks.stats != nullptr)
                {
                    hooks.stats->droppedDraws = hooks.stats->droppedDraws + 1;
                    replay_detail::logDroppedDraw(type, c.image, 0);
                }
                break;
            }
            case RenderCmd::modulateOpacity:
            {
                auto c = reader.read<OpacityPOD>();
                if (cur)
                {
                    cur->modulateOpacity(c.opacity);
                }
                break;
            }
            case RenderCmd::modulateColor:
            {
                auto c = reader.read<ModulateColorPOD>();
                if (cur)
                {
                    cur->modulateColor(c.color, c.replace != 0);
                }
                break;
            }

            case RenderCmd::canvasContentBegin:
            {
                auto c = reader.read<CanvasContentPOD>();
                cur = hooks.beginCanvasContent
                          ? hooks.beginCanvasContent(c.canvasId &
                                                         kCanvasHandleMask,
                                                     c.clearColor)
                          : nullptr;
                break;
            }
            case RenderCmd::canvasContentEnd:
            {
                reader.read<ResIdPOD>(); // advance past the canvas id
                cur = renderer;          // back to the screen; null drops draws
                break;
            }
        }
    }
    if (reader.overrun())
    {
        fprintf(stderr,
                "rive replay ABORT: payload overrun at byte %zu of %zu\n",
                reader.position(),
                commands.size());
        assert(false);
    }
}

} // namespace rive::cmd
