#include "rive/artboard.hpp"
#include "rive/file.hpp"
#ifdef WITH_RIVE_SCRIPTING_WASM
#include "rive/wasm/wasm_scripting_vm.hpp"
#endif
#include "rive/animation/keyframe_interpolator.hpp"
#include "rive/artboard_component_list.hpp"
#include "rive/backboard.hpp"
#include "rive/component.hpp"
#include "rive/container_component.hpp"
#include "rive/focus_data.hpp"
#include "rive/input/focus_manager.hpp"
#include "rive/semantic/semantic_data.hpp"
#include "rive/semantic/semantic_manager.hpp"
#include "rive/semantic/semantic_node.hpp"
#include "rive/input/focusable.hpp"
#include "rive/animation/linear_animation_instance.hpp"
#include "rive/custom_property_color.hpp"
#include "rive/custom_property_number.hpp"
#include "rive/custom_property_trigger.hpp"
#include "rive/math/math_types.hpp"
#include "rive/shapes/paint/color.hpp"
#include "rive/dependency_sorter.hpp"
#include "rive/data_bind/data_bind.hpp"
#include "rive/data_bind/data_bind_context.hpp"
#include "rive/draw_rules.hpp"
#include "rive/draw_target.hpp"
#include "rive/audio_event.hpp"
#include "rive/draw_target_placement.hpp"
#include "rive/drawable.hpp"
#include "rive/animation/keyed_object.hpp"
#include "rive/animation/keyframe.hpp"
#include "rive/factory.hpp"
#include "rive/renderer.hpp"
#include "rive/shapes/paint/shape_paint.hpp"
#include "rive/watermark.hpp"
#include "rive/importers/import_stack.hpp"
#include "rive/importers/backboard_importer.hpp"
#include "rive/layout_component.hpp"
#include "rive/node.hpp"
#include "rive/foreground_layout_drawable.hpp"
#include "rive/nested_artboard.hpp"
#include "rive/nested_artboard_leaf.hpp"
#include "rive/nested_artboard_layout.hpp"
#include "rive/animation/nested_state_machine.hpp"
#include "rive/joystick.hpp"
#include "rive/data_bind/data_bind.hpp"
#include "rive/data_bind_flags.hpp"
#include "rive/animation/nested_bool.hpp"
#include "rive/animation/nested_number.hpp"
#include "rive/animation/nested_trigger.hpp"
#include "rive/viewmodel/viewmodel_instance.hpp"
#include "rive/viewmodel/viewmodel_instance_value.hpp"
#include "rive/viewmodel/viewmodel.hpp"
#include "rive/view_model_type.hpp"
#include "rive/data_bind/data_context.hpp"
#include "rive/animation/state_machine_input_instance.hpp"
#include "rive/animation/state_machine_instance.hpp"
#include "rive/shapes/shape.hpp"
#include "rive/shapes/path_composer.hpp"
#include "rive/text/text_style.hpp"
#include "rive/text/text_variation_helper.hpp"
#include "rive/shapes/clipping_shape.hpp"
#include "rive/text/text_value_run.hpp"
#include "rive/event.hpp"
#include "rive/assets/audio_asset.hpp"
#include "rive/layout/layout_data.hpp"
#include "rive/profiler/profiler_macros.h"
#include "rive/scripted/scripted_object.hpp"
#ifdef WITH_RIVE_SCRIPTING
#ifdef WITH_RIVE_SCRIPTING_LUAU
#include "rive/lua/rive_lua_libs.hpp"
#endif
#endif
#include "rive/async/work_pool.hpp"
#include "rive/bitmap_cache.hpp"
#include "rive/layer_mask.hpp"
#ifdef RIVE_CANVAS
#include "rive/offscreen_raster.hpp"
#include "rive/renderer/render_context.hpp"
#include "rive/renderer/render_canvas.hpp"
#include "rive/renderer/cmd/deferred_canvas_host.hpp"
#include "rive/shapes/paint/image_sampler.hpp"
#include <algorithm>
#include <array>
#include <cmath>
#endif

#include <set>
#include <unordered_map>

using namespace rive;

uint64_t Artboard::sm_frameId = 0;
#ifdef TESTING
uint64_t Artboard::sm_layoutPassCount = 0;
uint64_t Artboard::sm_dirtNotifications = 0;
#endif

Artboard::Artboard()
{
    // Artboards need to override default clip value to true.
    m_Clip = true;
#ifdef WITH_RIVE_TOOLS
    callbackUserData = this;
#endif
}

#ifdef TESTING
Artboard::Artboard(Factory* factory) : m_Factory(factory) { m_Clip = true; }
#endif

Artboard::~Artboard()
{
    // Tear the focus tree down FIRST, while every component is still alive.
    // Detaching a focused node clears focus, and that runs blur callbacks
    // (FocusData::blurred walks parents and siblings) — which must not fire
    // once the m_Objects loop below has started deleting those siblings.
    //
    // Only when we own the manager: an adopted one belongs to a host artboard
    // or to Dart, either of which may already be gone by the time a finalizer
    // frees us, so m_activeFocusManager is not safe to touch. Those artboards
    // are cleaned up explicitly by whoever adopted them —
    // NestedArtboard::updateArtboard and ArtboardComponentList::removeArtboard
    // both call cleanupFocusTree() before teardown — and a host being torn
    // down has already run this same block against the shared manager, so
    // nothing in a nested subtree is still focused by the time we reach it.
    if (m_ownedFocusManager != nullptr &&
        m_activeFocusManager == m_ownedFocusManager.get())
    {
#ifdef WITH_RIVE_TOOLS
        m_ownedFocusManager->setFocusChangedCallback(nullptr);
        m_ownedFocusManager->setScrollIntoViewCallback(nullptr);
#endif
        cleanupFocusTree();
    }

#ifdef WITH_RIVE_AUDIO
#ifdef EXTERNAL_RIVE_AUDIO_ENGINE
    auto audioEngine = m_audioEngine != nullptr
                           ? m_audioEngine
                           : AudioEngine::RuntimeEngine(false);
#else
    auto audioEngine = AudioEngine::RuntimeEngine(false);
#endif
    if (audioEngine)
    {
        audioEngine->stop(this);
    }
#endif
    unbind();

    // ViewModelInstance and ViewModelInstanceValue inherit from RefCnt.
    //
    // ViewModelInstance (VMI) ownership: the artboard releases every VMI in
    // its m_Objects via unref(). NestedArtboard borrows its stateful child VMI
    // without bumping the refcount; dynamically-created bound VMIs are not in
    // m_Objects and are released by NestedArtboard itself.
    //
    // ViewModelInstanceValue (VMV) ownership: always owned by their parent
    // ViewModelInstance via rcp<> in m_PropertyValues. When VMI is deleted,
    // its destructor clears m_PropertyValues, which unrefs and deletes VMVs.
    //
    // Strategy:
    // 1) Identify VMI/VMV objects by pointer (safe is<>() check BEFORE any
    // deletions).
    // 2) Delete everything else immediately, deferring VMI unref until after
    // hierarchy components are gone.
    std::set<Core*> vmObjects;
    std::set<ViewModelInstance*> deferredVmiUnrefs;

    // First pass: identify ViewModelInstance and ViewModelInstanceValue
    // objects while memory is valid (before any deletions). Precompute which
    // VMIs should be released so we never dereference pointers after deletes.
    // Also detach FocusData from their nodes: with an adopted manager the
    // focus tree above wasn't torn down, and deleting a focused node blurs the
    // chain, which must not call into components already deleted.
    auto preDeletePass = [&](Core* object) {
        if (object == nullptr || object == this)
        {
            return;
        }
        if (object->is<FocusData>())
        {
            object->as<FocusData>()->detachFocusable();
            return;
        }
        if (object->is<ViewModelInstance>())
        {
            vmObjects.insert(object);
            deferredVmiUnrefs.insert(object->as<ViewModelInstance>());
            return;
        }
        if (object->is<ViewModelInstanceValue>())
        {
            vmObjects.insert(object);
        }
    };
    for (auto object : m_Objects)
    {
        preDeletePass(object);
    }
    for (auto object : m_invalidObjects)
    {
        preDeletePass(object);
    }

    auto isVmObject = [&](Core* object) -> bool {
        return vmObjects.count(object) != 0;
    };

    // Second pass: delete non-VM objects.
    for (auto object : m_Objects)
    {
        if (object == nullptr || object == this)
        {
            continue;
        }
        if (isVmObject(object))
        {
            continue;
        }
        delete object;
    }
    for (auto object : m_invalidObjects)
    {
        if (object == nullptr)
        {
            continue;
        }
        if (isVmObject(object))
        {
            continue;
        }
        delete object;
    }

    // Now release deferred ViewModelInstances after hierarchy components have
    // been destroyed. Releasing via unref() keeps RefCnt ownership semantics
    // intact and cascades to VMVs via m_PropertyValues rcps.
    for (auto* vmi : deferredVmiUnrefs)
    {
        vmi->unref();
    }

    deleteDataBinds();

    // Instances reference back to the original artboard's animations and state
    // machines, so don't delete them here, they'll get cleaned up when the
    // source is deleted.
    // TODO: move this logic into ArtboardInstance destructor???
    if (!m_IsInstance)
    {
        for (auto object : m_Animations)
        {
            delete object;
        }
        for (auto object : m_StateMachines)
        {
            delete object;
        }
    }
    m_dirtyLayout.clear();
}

static bool canContinue(StatusCode code)
{
    // We currently only cease loading on invalid object.
    return code != StatusCode::InvalidObject;
}

bool Artboard::validateObjects()
{
    auto size = m_Objects.size();
    std::vector<bool> valid(size);

    // Max iterations..
    for (int cycle = 0; cycle < 100; cycle++)
    {
        bool changed = false;
        for (size_t i = 1; i < size; i++)
        {
            auto object = m_Objects[i];
            if (object == nullptr)
            {
                // objects can be null if they were not understood by this
                // runtime.
                continue;
            }
            bool wasValid = valid[i];
            bool isValid = object->validate(this);
            if (wasValid != isValid)
            {
                changed = true;
                valid[i] = isValid;
            }
        }
        if (changed)
        {
            // Delete invalid objects.
            for (size_t i = 1; i < size; i++)
            {
                if (valid[i])
                {
                    continue;
                }
                // Instead of immediately deleting invalid objects, we keep them
                // around in case other objects are referencing them. One
                // example is the backboard_importer keeping a reference on its
                // m_FileAssetReferencers. So the invalid objects are taken out
                // of the objects list but only deleted when the artboard is
                // destroyed.
                m_invalidObjects.push_back(m_Objects[i]);
                m_Objects[i] = nullptr;
            }
        }
        else
        {
            break;
        }
    }

    return true;
}

void Artboard::reinstanceNestedArtboards(Factory* factory)
{
    for (auto object : m_Objects)
    {
        if (object == nullptr || !object->is<NestedArtboard>())
        {
            continue;
        }
        auto nested = object->as<NestedArtboard>();
        Artboard* current = nested->sourceArtboard();
        if (current == nullptr || !current->isInstance() ||
            current->m_artboardSource == nullptr)
        {
            continue;
        }
        auto replacement =
            current->m_artboardSource->instance<ArtboardInstance>(factory);
        if (replacement != nullptr)
        {
            nested->referencedArtboard(replacement.release());
        }
    }
}

StatusCode Artboard::initialize()
{
    StatusCode code;

    // these will be re-built in update() -- are they needed here?
    m_layout = Layout(0.0f, 0.0f, width(), height());

#ifdef WITH_RIVE_LAYOUT
    markLayoutDirty(this);
#endif
    // onAddedDirty guarantees that all objects are now available so they can be
    // looked up by index/id. This is where nodes find their parents, but they
    // can't assume that their parent's parent will have resolved yet.
    for (auto object : m_Objects)
    {
        if (object == nullptr)
        {
            // objects can be null if they were not understood by this runtime.
            continue;
        }
        if (!canContinue(code = object->onAddedDirty(this)))
        {
            return code;
        }
    }

    // Animations and StateMachines initialize only once on the source/origin
    // Artboard. Instances will hold references to the original Animations and
    // StateMachines, so running this code for instances will effectively
    // initialize them twice. This can lead to unpredictable behaviour. One such
    // example was that resolved objects like listener inputs were being added
    // to lists twice.
    if (!isInstance())
    {
        for (auto object : m_Animations)
        {
            if (!canContinue(code = object->onAddedDirty(this)))
            {
                return code;
            }
        }

        for (auto object : m_StateMachines)
        {
            if (!canContinue(code = object->onAddedDirty(this)))
            {
                return code;
            }
        }
        if (m_Animations.size() == 0 && m_StateMachines.size() == 0)
        {
            auto sm = new StateMachine();
            sm->name("Auto Generated State Machine");
            m_StateMachines.push_back(sm);
        }
    }

    // Store a map of the drawRules to make it easier to lookup the matching
    // rule for a transform component.
    std::unordered_map<Core*, DrawRules*> componentDrawRules;

#ifdef WITH_RIVE_EDITOR
    // Editor builds move typed-child registration (paths on shapes,
    // nested animations on NestedArtboard, skins, constraints, ...) out
    // of onAdded* and into editorParentChanged, driven by the coop
    // hydration passes. initialize() only ever runs for .riv-imported
    // artboards, which never see those passes — run the registration
    // sweep here or the typed lists stay empty (frozen rigs, zero
    // bounds, unresolvable nested inputs). Must happen BEFORE the
    // onAddedClean walk below: consumers like NestedArtboard mount
    // their nested state machines from the typed lists inside
    // onAddedClean. Parent pointers and child lists are wired by the
    // onAddedDirty pass above. Registrations are contractually
    // idempotent on `to`, so the pump's hydrateRuntimeArtboard doing
    // this again is harmless.
    for (auto object : m_Objects)
    {
        if (object != nullptr && object->is<Component>())
        {
            auto* component = object->as<Component>();
            if (auto* componentParent = component->parent())
            {
                component->editorParentChanged(nullptr, componentParent);
            }
        }
    }
#endif

    // onAddedClean is called when all individually referenced components have
    // been found and so components can look at other components' references and
    // assume that they have resolved too. This is where the whole hierarchy is
    // linked up and we can traverse it to find other references (my parent's
    // parent should be type X can be checked now).
    for (auto object : m_Objects)
    {
        if (object == nullptr)
        {
            continue;
        }
        if (!canContinue(code = object->onAddedClean(this)))
        {
            return code;
        }
        if (object->is<Component>())
        {
            auto resettable = ResettingComponent::from(object->as<Component>());
            if (resettable)
            {
                m_Resettables.push_back(resettable);
            }
        }
        switch (object->coreType())
        {
            case DrawRulesBase::typeKey:
            {
                DrawRules* rules = static_cast<DrawRules*>(object);
                Core* component = resolve(rules->parentId());
                if (component != nullptr)
                {
                    componentDrawRules[component] = rules;
                }
                else
                {
                    fprintf(stderr,
                            "Artboard::initialize - Draw rule targets missing "
                            "component width id %u\n",
                            static_cast<uint32_t>(rules->parentId()));
                }
                break;
            }
            case NestedArtboardBase::typeKey:
            case NestedArtboardLeafBase::typeKey:
            case NestedArtboardLayoutBase::typeKey:
            {
                m_NestedArtboards.push_back(object->as<NestedArtboard>());
                m_ArtboardHosts.push_back(object->as<NestedArtboard>());
                break;
            }
            case ArtboardComponentListBase::typeKey:
                m_ComponentLists.push_back(object->as<ArtboardComponentList>());
                m_ArtboardHosts.push_back(object->as<ArtboardComponentList>());
                break;
            case JoystickBase::typeKey:
            {
                Joystick* joystick = object->as<Joystick>();
                if (!joystick->canApplyBeforeUpdate())
                {
                    m_JoysticksApplyBeforeUpdate = false;
                }
                joystick->addDependents(this);
                m_Joysticks.push_back(joystick);
                break;
            }
            case BitmapCacheBase::typeKey:
                m_BitmapCache = object->as<BitmapCache>();
                break;
        }
        auto advancingComponent = AdvancingComponent::from(object);
        if (advancingComponent)
        {
            m_advancingComponents.push_back(advancingComponent);
        }
    }

    if (!isInstance())
    {
        for (auto object : m_Animations)
        {
            if (!canContinue(code = object->onAddedClean(this)))
            {
                return code;
            }
        }

        for (auto object : m_StateMachines)
        {
            if (!canContinue(code = object->onAddedClean(this)))
            {
                return code;
            }
        }
    }

    // Multi-level references have been built up, now we can
    // actually mark what's dependent on what.
    for (auto object : m_Objects)
    {
        if (object == nullptr)
        {
            continue;
        }
        if (object->is<Component>())
        {
            object->as<Component>()->buildDependencies();
        }
        if (object->is<Drawable>() && object != this)
        {
            Drawable* drawable = object->as<Drawable>();
            m_Drawables.push_back(drawable);
            // Move the foreground drawable before its parent. We traverse the
            // added list of drawables and swap their positions with the
            // foreground drawable until we find the parent
            if (drawable->is<ForegroundLayoutDrawable>())
            {
                auto parent = drawable->parent();
                auto index = m_Drawables.size() - 1;
                while (index >= 1)
                {
                    auto swappingDrawable = m_Drawables[index - 1];
                    std::swap(m_Drawables[index - 1], m_Drawables[index]);
                    if (swappingDrawable == parent)
                    {
                        break;
                    }
                    index--;
                }
            }

            for (ContainerComponent* parent = drawable; parent != nullptr;
                 parent = parent->parent())
            {
                auto itr = componentDrawRules.find(parent);
                if (itr != componentDrawRules.end())
                {
                    drawable->flattenedDrawRules = itr->second;
                    break;
                }
            }
        }
        else if (object->is<ClippingShape>())
        {
            m_clippingShapes.push_back(object->as<ClippingShape>());
        }
        else if (object->is<LayerMask>())
        {
            m_layerMasks.push_back(object->as<LayerMask>());
        }
    }
    // A layout only needs a DrawableProxy if it paints, clips, can gain a clip
    // at runtime, or is an interaction/listener hit target. Those deferred
    // reasons are stamped as ForceDrawableProxy when their references resolve
    // (KeyedObject::onAddedDirty, DataBind::target, ScrollConstraint, and
    // StateMachineListener::onAddedClean; source-only ones are carried to
    // instances by LayoutComponent::clone) -- guaranteeing the proxy exists
    // before this first, one-time injection. See needsDrawableProxy.

    // Iterate over the drawables in order to inject proxies for layouts
    std::vector<LayoutComponent*> layouts;
    for (int i = 0; i < m_Drawables.size(); i++)
    {
        auto drawable = m_Drawables[i];
        LayoutComponent* currentLayout = nullptr;
        bool isInCurrentLayout = true;
        if (!layouts.empty())
        {
            currentLayout = layouts.back();
            isInCurrentLayout = drawable->isChildOfLayout(currentLayout);
        }
        // We inject a DrawableProxy after all of the children of a
        // LayoutComponent so that we can draw a stroke above and background
        // below the children This also allows us to clip the children. Layouts
        // that will never paint or clip skip the proxy entirely (it would draw
        // nothing) -- pure containers are the common case.
        if (currentLayout != nullptr && !isInCurrentLayout)
        {
            // This is the first item in the list of drawables that isn't a
            // child of the layout, so we insert a proxy before it
            do
            {
                if (currentLayout->needsDrawableProxy())
                {
                    m_Drawables.insert(m_Drawables.begin() + i,
                                       currentLayout->proxy());
                    i += 1;
                }
                layouts.pop_back();
                if (!layouts.empty())
                {
                    currentLayout = layouts.back();
                }
            } while (!layouts.empty() &&
                     !drawable->isChildOfLayout(currentLayout));
        }
        if (drawable->is<LayoutComponent>())
        {
            layouts.push_back(drawable->as<LayoutComponent>());
        }
    }
    while (!layouts.empty())
    {
        auto layout = layouts.back();
        if (layout->needsDrawableProxy())
        {
            m_Drawables.push_back(layout->proxy());
        }
        layouts.pop_back();
    }

    sortDependencies();

    std::vector<DrawRules*> rulesList;
    // Build the rules in the right order. We use the map componentDrawRules
    // to make sure we traverse the objects in the right order from parent
    // to child, and add the rules accordingly.
    for (auto object : m_Objects)
    {
        if (object == nullptr)
        {
            continue;
        }
        auto itr = componentDrawRules.find(object);
        if (itr != componentDrawRules.end())
        {
            rulesList.emplace_back(componentDrawRules[object]);
        }
    }
    DrawTarget root;
    // Build up the draw order. Look for draw targets and build
    // their dependencies.
    for (auto rules : rulesList)
    {
        for (auto child : rules->children())
        {
            auto target = child->as<DrawTarget>();
            root.addDependent(target);
            auto dependentRules = target->drawable()->flattenedDrawRules;
            if (dependentRules != nullptr)
            {
                // Because we don't store targets on rules, we need
                // to find the targets that belong to this rule
                // here.
                for (auto object : m_Objects)
                {
                    if (object != nullptr && object->is<DrawTarget>())
                    {
                        DrawTarget* dependentTarget = object->as<DrawTarget>();
                        if (dependentTarget->parent() == dependentRules)
                        {
                            dependentTarget->addDependent(target);
                        }
                    }
                }
            }
        }
    }
    DependencySorter sorter;
    std::vector<Component*> drawTargetOrder;
    sorter.sort(&root, drawTargetOrder);
    if (drawTargetOrder.size() > 0)
    {
        auto itr = drawTargetOrder.begin();
        itr++;
        while (itr != drawTargetOrder.end())
        {
            m_DrawTargets.push_back(static_cast<DrawTarget*>(*itr++));
        }
    }

    initScriptedObjects();
    return StatusCode::Ok;
}

void Artboard::sortDrawOrder()
{
    m_drawOrderChangeCounter =
        m_drawOrderChangeCounter == std::numeric_limits<uint8_t>::max()
            ? 0
            : m_drawOrderChangeCounter + 1;
    for (auto target : m_DrawTargets)
    {
        target->first = target->last = nullptr;
    }

    m_FirstDrawable = nullptr;
    Drawable* lastDrawable = nullptr;
    for (auto drawable : m_Drawables)
    {
        auto rules = drawable->flattenedDrawRules;
        if (rules != nullptr && rules->activeTarget() != nullptr)
        {

            auto target = rules->activeTarget();
            if (target->first == nullptr)
            {
                target->first = target->last = drawable;
                drawable->prev = drawable->next = nullptr;
            }
            else
            {
                target->last->next = drawable;
                drawable->prev = target->last;
                target->last = drawable;
                drawable->next = nullptr;
            }
        }
        else
        {
            drawable->prev = lastDrawable;
            drawable->next = nullptr;
            if (lastDrawable == nullptr)
            {
                lastDrawable = m_FirstDrawable = drawable;
            }
            else
            {
                lastDrawable->next = drawable;
                lastDrawable = drawable;
            }
        }
    }

    for (auto rule : m_DrawTargets)
    {
        if (rule->first == nullptr)
        {
            continue;
        }
        auto targetDrawable = rule->drawable();
        switch (rule->placement())
        {
            case DrawTargetPlacement::before:
            {
                if (targetDrawable->prev != nullptr)
                {
                    targetDrawable->prev->next = rule->first;
                    rule->first->prev = targetDrawable->prev;
                }
                if (targetDrawable == m_FirstDrawable)
                {
                    m_FirstDrawable = rule->first;
                }
                targetDrawable->prev = rule->last;
                rule->last->next = targetDrawable;
                break;
            }
            case DrawTargetPlacement::after:
            {
                if (targetDrawable->next != nullptr)
                {
                    targetDrawable->next->prev = rule->last;
                    rule->last->next = targetDrawable->next;
                }
                if (targetDrawable == lastDrawable)
                {
                    lastDrawable = rule->last;
                }
                targetDrawable->next = rule->first;
                rule->first->prev = targetDrawable;
                break;
            }
        }
    }

    m_FirstDrawable = lastDrawable;

    // Interleave clipping operations between drawables that share the same
    // common clippings. Each clipping operation has a start and an end.
    for (auto& clippingShape : m_clippingShapes)
    {
        clippingShape->resetDrawables();
    }
    Drawable* currentDrawable = m_FirstDrawable;
    Drawable* nextDrawable = nullptr;
    std::vector<ClippingShape*> _clippingStack;
    while (currentDrawable)
    {
        currentDrawable->needsSaveOperation(true);
        const auto& drawableClippingShapes = currentDrawable->clippingShapes();
        // Remove all clippings that are not part of the current drawable. Since
        // they are applied as a stack, if one clipping is removed, all
        // subsequent clippings from the stack need to be removed as well
        size_t removingIndex = _clippingStack.size();
        for (size_t i = 0; i < _clippingStack.size(); ++i)
        {
            auto& cl = _clippingStack[i];
            // Check if this clipping should stay (is in both stack and
            // drawable's clippings)
            bool shouldStay = std::find(drawableClippingShapes.begin(),
                                        drawableClippingShapes.end(),
                                        cl) != drawableClippingShapes.end();
            if (!shouldStay)
            {
                removingIndex = i;
                break;
            }
        }

        // Remove all clippings from stack in the reverse order they were added
        if (_clippingStack.size() > 0 && removingIndex < _clippingStack.size())
        {

            size_t i = _clippingStack.size() - 1;
            while (i >= removingIndex)
            {
                auto& clippingShape = _clippingStack[i];
                // Insert in the drawing list a clipEnd for each clipping that
                // is removed
                auto proxyDrawable =
                    clippingShape->createProxyDrawable(&clippingShape->clipEnd);
                if (nextDrawable)
                {
                    proxyDrawable->next = nextDrawable;
                    nextDrawable->prev = proxyDrawable;
                }
                else
                {
                    fprintf(stderr,
                            "Error - adding clip end as first operation\n");
                }
                proxyDrawable->prev = currentDrawable;
                currentDrawable->next = proxyDrawable;
                nextDrawable = proxyDrawable;
                if (i == 0)
                {
                    break;
                }
                i--;
            }
            _clippingStack.erase(_clippingStack.begin() + removingIndex,
                                 _clippingStack.end());
        }
        // Find clippings that are applied to the drawable but are not on the
        // stack
        for (auto& clippingShape : drawableClippingShapes)
        {
            auto itr = std::find(_clippingStack.begin(),
                                 _clippingStack.end(),
                                 clippingShape);
            if (itr == _clippingStack.end())
            {
                auto proxyDrawable = clippingShape->createProxyDrawable(
                    &clippingShape->clipStart);
                if (nextDrawable)
                {
                    proxyDrawable->next = nextDrawable;
                    nextDrawable->prev = proxyDrawable;
                }
                else
                {
                    m_FirstDrawable = proxyDrawable;
                }
                proxyDrawable->prev = currentDrawable;
                currentDrawable->next = proxyDrawable;
                nextDrawable = proxyDrawable;
                _clippingStack.push_back(clippingShape);
            }
        }
        nextDrawable = currentDrawable;
        currentDrawable = currentDrawable->prev;
    }
    // Add closing calls to remaining clippings in the stack
    if (_clippingStack.size() > 0)
    {

        for (int i = (int)(_clippingStack.size() - 1); i >= 0; i--)
        {
            auto& clippingShape = _clippingStack[i];
            auto proxyDrawable =
                clippingShape->createProxyDrawable(&clippingShape->clipEnd);
            if (nextDrawable)
            {
                nextDrawable->prev = proxyDrawable;
                proxyDrawable->next = nextDrawable;
            }
            proxyDrawable->prev = nullptr; // End of list
            nextDrawable = proxyDrawable;
        }
    }
    interleaveLayerMasks();
    clearRedundantOperations();
}

// True when `d` belongs inside a bracket whose members are `members`. Pure
// bracket operations (clip and mask markers) are always allowed: they are
// nested structure, not content. A DrawableProxy is allowed when the component
// it stands in for is a member -- a LayoutComponent's proxy is injected by the
// artboard and so never appears in a subtree walk, but its save()+clipPath()
// has to sit inside the same bracket as the restore() in its draw().
static bool spansMember(Drawable* d,
                        const std::unordered_set<Drawable*>& members)
{
    if (members.count(d) != 0)
    {
        return true;
    }
    if (!d->isProxy())
    {
        return false;
    }
    if (d->isClipStart() || d->isClipEnd() || d->isMaskStart() ||
        d->isMaskEnd())
    {
        return true;
    }
    Drawable* stands = d->hittableComponent();
    return stands != nullptr && members.count(stands) != 0;
}

bool Artboard::spliceLayerMaskBracket(LayerMask* mask,
                                      const std::vector<Drawable*>& members,
                                      LayerMaskOp startOp,
                                      LayerMaskOp endOp,
                                      LayerMaskProxyDrawable** startOut)
{
    if (startOut != nullptr)
    {
        *startOut = nullptr;
    }
    if (members.empty())
    {
        return false;
    }
    std::unordered_set<Drawable*> memberSet(members.begin(), members.end());

    // `next` is earlier in draw order, `prev` later: the walk from
    // m_FirstDrawable follows prev, so first/last here are in draw order.
    Drawable* first = nullptr;
    Drawable* last = nullptr;
    for (auto d = m_FirstDrawable; d != nullptr; d = d->prev)
    {
        if (memberSet.count(d) != 0)
        {
            if (first == nullptr)
            {
                first = d;
            }
            last = d;
        }
    }
    if (first == nullptr)
    {
        // The members are not in this artboard's draw list at all (all hidden
        // behind a collapsed parent, say).
        return false;
    }

    // Our markers have to nest with every bracket already in the list, never
    // interleave: the draw walk is handed a [start, end) range and would run
    // off the list if an inner end marker escaped our outer one. The member
    // extremes are not necessarily balanced -- a mask processed before us may
    // have bracketed our first or last member -- so grow the range outward
    // until it is. Bracket markers are always allowed inside a span, so growing
    // can only make the contiguity check below easier.
    bool grew = true;
    while (grew)
    {
        grew = false;
        // Starts whose end is inside the range, and ends whose start is before
        // it.
        int clipDepth = 0, maskDepth = 0;
        int clipDeficit = 0, maskDeficit = 0;
        for (auto d = first;; d = d->prev)
        {
            if (d->isClipStart())
            {
                ++clipDepth;
            }
            else if (d->isClipEnd())
            {
                clipDepth > 0 ? --clipDepth : ++clipDeficit;
            }
            else if (d->isMaskStart())
            {
                ++maskDepth;
            }
            else if (d->isMaskEnd())
            {
                maskDepth > 0 ? --maskDepth : ++maskDeficit;
            }
            if (d == last)
            {
                break;
            }
        }
        // Pull the start back over the openers whose closers we contain.
        while (clipDeficit > 0 || maskDeficit > 0)
        {
            Drawable* before = first->next;
            if (before == nullptr)
            {
                break;
            }
            if (maskDeficit > 0 && before->isMaskStart())
            {
                --maskDeficit;
            }
            else if (clipDeficit > 0 && before->isClipStart())
            {
                --clipDeficit;
            }
            else
            {
                break;
            }
            first = before;
            grew = true;
        }
        // Push the end forward over the closers whose openers we contain.
        while (clipDepth > 0 || maskDepth > 0)
        {
            Drawable* after = last->prev;
            if (after == nullptr)
            {
                break;
            }
            if (maskDepth > 0 && after->isMaskEnd())
            {
                --maskDepth;
            }
            else if (clipDepth > 0 && after->isClipEnd())
            {
                --clipDepth;
            }
            else
            {
                break;
            }
            last = after;
            grew = true;
        }
        if (!grew && (clipDeficit > 0 || maskDeficit > 0 || clipDepth > 0 ||
                      maskDepth > 0))
        {
            // Could not balance: some bracket genuinely half-overlaps this
            // range, and no placement of our markers avoids crossing it.
            return false;
        }
    }

    // Contiguity. A draw rule can lift an unrelated drawable into the middle of
    // a subtree's span; masking it too would be silently wrong, and splitting
    // into two brackets would composite the mask twice. Refuse instead, and let
    // the caller draw the content unmasked.
    for (auto d = first;; d = d->prev)
    {
        if (!spansMember(d, memberSet))
        {
            return false;
        }
        if (d == last)
        {
            break;
        }
    }

    auto* startMarker = mask->createProxyDrawable(startOp);
    auto* endMarker = mask->createProxyDrawable(endOp);

    // Insert startMarker immediately before `first` in draw order.
    Drawable* before = first->next;
    startMarker->next = before;
    startMarker->prev = first;
    if (before != nullptr)
    {
        before->prev = startMarker;
    }
    else
    {
        m_FirstDrawable = startMarker;
    }
    first->next = startMarker;

    // Insert endMarker immediately after `last` in draw order.
    Drawable* after = last->prev;
    endMarker->prev = after;
    endMarker->next = last;
    if (after != nullptr)
    {
        after->next = endMarker;
    }
    last->prev = endMarker;

    startMarker->pairedEnd(endMarker);
    if (startOut != nullptr)
    {
        *startOut = startMarker;
    }
    return true;
}

void Artboard::interleaveLayerMasks()
{
    if (m_layerMasks.empty())
    {
        return;
    }
    for (auto& mask : m_layerMasks)
    {
        mask->resetDrawables();
    }
    for (auto& mask : m_layerMasks)
    {
        // A self-referential mask is inert: its source sits inside the range it
        // would rasterize, so bracketing it would recurse forever.
        if (mask->isSelfReferential())
        {
            continue;
        }
        // Collect the drawables this mask applies to. Done per mask rather than
        // from one shared index because each splice shifts the list.
        std::vector<Drawable*> masked;
        for (auto d = m_FirstDrawable; d != nullptr; d = d->prev)
        {
            const auto& masks = d->layerMasks();
            if (std::find(masks.begin(), masks.end(), mask) != masks.end())
            {
                masked.push_back(d);
            }
        }
        LayerMaskProxyDrawable* start = nullptr;
        if (!spliceLayerMaskBracket(mask,
                                    masked,
                                    LayerMaskOp::maskStart,
                                    LayerMaskOp::maskEnd,
                                    &start))
        {
            continue;
        }
        // Only bracket the source once the masked range is genuinely bracketed:
        // suppressing the source while the content draws unmasked would just
        // make the mask art vanish for nothing.
        LayerMaskProxyDrawable* sourceStart = nullptr;
        if (spliceLayerMaskBracket(mask,
                                   mask->sourceDrawables(),
                                   LayerMaskOp::sourceStart,
                                   LayerMaskOp::sourceEnd,
                                   &sourceStart))
        {
            mask->sourceBracket(sourceStart, sourceStart->pairedEnd());
        }
    }
}

// Look for drawables that are preceeding and succeeding drawables that call
// save and restore. If found, the drawable does not need to call save and
// restore itself.
void Artboard::clearRedundantOperations()
{
    Drawable* currentDrawable = m_FirstDrawable;
    bool prevAppliedSave = false;
    // Keep a stack of clipStart operation results to apply the same operation
    // to its clipEnd
    std::vector<bool> appliedClippingSaveOperations;
    while (currentDrawable)
    {
        currentDrawable->needsSaveOperation(true);
        // If previous operation applied a save operation
        if (prevAppliedSave)
        {
            // With consecutive clippings, we can skip the save and restore
            // operation since the previous one has applied it
            if (currentDrawable->isClipStart())
            {
                appliedClippingSaveOperations.push_back(false);
                currentDrawable->needsSaveOperation(false);
            }
            else if (currentDrawable->isClipEnd())
            {
                // Apply or skip the clipEnd Restore operation matching its clip
                // start counterpart
                auto operationApplied = appliedClippingSaveOperations.back();
                appliedClippingSaveOperations.pop_back();
                currentDrawable->needsSaveOperation(operationApplied);
            }
            else
            {
                // Check if next is clip end, if it is, we can skip the drawable
                // save/restore because it is tightly wrapped in a clipping
                // operation
                auto nextDrawable = currentDrawable->prev;
                if (nextDrawable->isClipEnd())
                {
                    currentDrawable->needsSaveOperation(false);
                }
            }
        }
        else if (currentDrawable->isClipStart())
        {
            appliedClippingSaveOperations.push_back(true);
        }
        else if (currentDrawable->isClipEnd())
        {
            // Apply or skip the clipEnd Restore operation matching its clip
            // start counterpart
            auto operationApplied = appliedClippingSaveOperations.back();
            currentDrawable->needsSaveOperation(operationApplied);
            appliedClippingSaveOperations.pop_back();
        }
        prevAppliedSave = currentDrawable->isClipStart() &&
                          (currentDrawable->willClip() || prevAppliedSave);
        currentDrawable = currentDrawable->prev;
    }
    assert(appliedClippingSaveOperations.size() == 0);
}

#ifdef WITH_RIVE_EDITOR
void Artboard::initLayoutForEditor()
{
    m_layout = Layout(0.0f, 0.0f, width(), height());
    // NOTE: intentionally skipping `markLayoutDirty(this)` — the full
    // layout pipeline isn't wired for coop-loaded artboards yet (no
    // style / Yoga node setup), and running syncStyleChanges on a
    // partial state has been observed to crash. Phase 2.1 adds the
    // layout pipeline back behind the `#ifdef WITH_RIVE_LAYOUT` once
    // the missing setup is in place.
}
#endif

Component* Artboard::componentForOrderEntry(
    const DependencyOrderEntry& entry) const
{
    if (entry.objectIndex >= m_Objects.size())
    {
        return nullptr;
    }
    Core* object = m_Objects[entry.objectIndex];
    if (object == nullptr)
    {
        return nullptr;
    }
    if (entry.helperSlot == 0)
    {
        return object->is<Component>() ? object->as<Component>() : nullptr;
    }
    // Slot 1 is the single owned helper for the types that have one. Add
    // further slots here if another Component gains an owned graph node.
    if (entry.helperSlot == 1)
    {
        if (object->is<Shape>())
        {
            return object->as<Shape>()->pathComposer();
        }
        if (object->is<TextStyle>())
        {
            return object->as<TextStyle>()->variationHelper();
        }
    }
    return nullptr;
}

const std::vector<Artboard::DependencyOrderEntry>* Artboard::
    dependencyOrderRecipe() const
{
    switch (m_RecipeState)
    {
        case RecipeState::valid:
            return &m_DependencyOrderRecipe;
        case RecipeState::unusable:
            return nullptr;
        case RecipeState::unbuilt:
            break;
    }

    // No reverse Component* -> index map is needed: sortDependencies() has
    // already stamped every component in m_DependencyOrder with its position
    // via m_GraphOrder, so one walk of m_Objects can scatter each entry
    // straight into its slot. That keeps recipe construction allocation-free
    // beyond the result vector, which matters because the source artboard is
    // re-decoded (and so re-builds this) on every editor regeneration.
    const size_t count = m_DependencyOrder.size();
    constexpr uint32_t unset = ~(uint32_t)0;
    m_DependencyOrderRecipe.assign(count, {unset, 0});
    size_t filled = 0;

    auto stamp = [&](const Component* component, uint32_t index, uint8_t slot) {
        if (component == nullptr)
        {
            return;
        }
        const unsigned int position = component->graphOrder();
        // A component the sort never placed keeps Component's sentinel, which
        // no order can hand out. One that a *previous, longer* order placed
        // keeps that order's position, which this one may well have handed to
        // somebody else -- so the stamp alone is not proof. Confirm the order
        // really holds this component where it claims to be, which is an exact
        // membership test no stale stamp can pass.
        if (position >= count || m_DependencyOrder[position] != component)
        {
            return;
        }
        DependencyOrderEntry& entry = m_DependencyOrderRecipe[position];
        if (entry.objectIndex != unset)
        {
            // One component reachable through two slots. Leave the first.
            return;
        }
        entry = {index, slot};
        filled++;
    };

    for (size_t i = 0; i < m_Objects.size(); i++)
    {
        Core* object = m_Objects[i];
        if (object == nullptr || !object->is<Component>())
        {
            continue;
        }
        const uint32_t index = (uint32_t)i;
        stamp(object->as<Component>(), index, 0);
        if (object->is<Shape>())
        {
            stamp(object->as<Shape>()->pathComposer(), index, 1);
        }
        else if (object->is<TextStyle>())
        {
            stamp(object->as<TextStyle>()->variationHelper(), index, 1);
        }
    }

    if (filled != count)
    {
        // Something in the order isn't addressable as index/slot (or the
        // graph-order stamps disagree). Don't emit a partial order.
        m_DependencyOrderRecipe.clear();
        m_RecipeState = RecipeState::unusable;
        return nullptr;
    }
    m_RecipeState = RecipeState::valid;
    return &m_DependencyOrderRecipe;
}

bool Artboard::replaySourceDependencyOrder(const Artboard* source)
{
    if (source == nullptr || source == this ||
        source->m_Objects.size() != m_Objects.size())
    {
        return false;
    }
    const std::vector<DependencyOrderEntry>* recipe =
        source->dependencyOrderRecipe();
    if (recipe == nullptr)
    {
        return false;
    }
    std::vector<Component*> order;
    order.reserve(recipe->size());
    for (const DependencyOrderEntry& entry : *recipe)
    {
        Component* component = componentForOrderEntry(entry);
        if (component == nullptr)
        {
            // A helper the source had but this instance doesn't (they are
            // lazily created). Fall back rather than emit a short order.
            return false;
        }
        order.push_back(component);
    }
    m_DependencyOrder = std::move(order);
    return true;
}

void Artboard::sortDependencies()
{
    // An instance replays its source's order instead of re-walking the graph;
    // see DependencyOrderEntry. Falls back to sorting whenever anything about
    // the instance doesn't line up.
    bool replayed = replaySourceDependencyOrder(m_artboardSource);

    if (!replayed)
    {
        DependencySorter sorter;
        sorter.sort(this, m_DependencyOrder);
    }
    unsigned int graphOrder = 0;
    for (auto component : m_DependencyOrder)
    {
        component->m_GraphOrder = graphOrder++;
    }
    m_DependencyOrderRecipe.clear();
    m_RecipeState = RecipeState::unbuilt;
    m_Dirt |= ComponentDirt::Components;
}

void Artboard::addObject(Core* object) { m_Objects.push_back(object); }

void Artboard::addAnimation(LinearAnimation* object)
{
    m_Animations.push_back(object);
}

void Artboard::addStateMachine(StateMachine* object)
{
    m_StateMachines.push_back(object);
}

void Artboard::addScriptedObject(ScriptedObject* object)
{
    m_ScriptedObjects.push_back(object);
}

void Artboard::initScriptedObjects()
{
    if (isInstance())
    {
        for (auto obj : m_ScriptedObjects)
        {
            if (obj->scriptAsset() != nullptr)
            {
                if (!obj->userLuaInitDone())
                {
                    obj->scriptAsset()->initScriptedObject(obj);
                }
                obj->hydrateScriptInputs();
            }
        }
    }
}

void Artboard::pollAsyncWork() { rive_pollAsyncWork(); }

void Artboard::advanceScriptedViewModels()
{
#ifdef WITH_RIVE_SCRIPTING_LUAU
    if (m_scriptingVM != nullptr)
    {
        if (auto* context = m_scriptingVM->context())
        {
            context->advanceDetachedViewModels();
        }
    }
#endif
#ifdef WITH_RIVE_SCRIPTING_WASM
    if (auto f = artboardFile())
    {
        for (auto& vm : f->wasmVMs())
        {
            vm->advanceDetachedViewModels();
        }
    }
#endif
}

Core* Artboard::resolve(Id id) const
{
#ifdef WITH_RIVE_EDITOR
    // Editor `Id` is `{client, object}` and objects come from two
    // sources that share the same namespace:
    //   • `.riv`-loaded objects — `CoreIdType::runtimeDeserialize`
    //     synthesizes `Id{0, runtime_index}` which indexes straight
    //     into `m_Objects` (same behavior as a runtime build).
    //   • Coop-delivered objects — stamped by the server with
    //     `client == 0` too, looked up via `m_editorResolver`'s
    //     CoopId map. Non-zero client always means a coop peer ID.
    // `m_Objects` first (runtime path) then fall through to the
    // resolver, so both sources resolve correctly without the caller
    // needing to know which. `kEmptyId == {0, 0}` is short-circuited
    // — `m_Objects[0]` is a legitimate object (the Artboard itself)
    // and would be a wrong answer for "no id set".
    if (id.empty())
        return nullptr;
    if (id.client == 0 && id.object < m_Objects.size())
    {
        if (auto* hit = m_Objects[id.object])
            return hit;
    }
    return m_editorResolver ? m_editorResolver->resolve(id) : nullptr;
#else
    // Runtime: single-source `Id` (a raw uint index) into `m_Objects`.
    return id < static_cast<int>(m_Objects.size()) ? m_Objects[id] : nullptr;
#endif
}

uint32_t Artboard::idOf(Core* object) const
{
    auto it = std::find(m_Objects.begin(), m_Objects.end(), object);

    if (it != m_Objects.end())
    {
        return castTo<uint32_t>(it - m_Objects.begin());
    }
    else
    {
        return 0;
    }
}

void Artboard::onComponentDirty(Component* component)
{
#ifdef TESTING
    sm_dirtNotifications++;
#endif
    wakeIfQuietRow();
    m_didChange = true;
    m_Dirt |= ComponentDirt::Components;

    /// If the order of the component is less than the current dirt
    /// depth, update the dirt depth so that the update loop can break
    /// out early and re-run (something up the tree is dirty).
    if (component->graphOrder() < m_DirtDepth)
    {
        m_DirtDepth = component->graphOrder();
    }
}

void Artboard::onDirty(ComponentDirt dirt)
{
#ifdef TESTING
    sm_dirtNotifications++;
#endif
    wakeIfQuietRow();
    m_Dirt |= ComponentDirt::Components;
}

#ifdef WITH_RIVE_LAYOUT
void Artboard::propagateSize()
{
    addDirt(ComponentDirt::Path);
    if (sharesLayoutWithHost())
    {
        m_host->markHostTransformDirty();
    }
#ifdef WITH_RIVE_TOOLS
    if (m_layoutChangedCallback != nullptr)
    {
        m_layoutChangedCallback(callbackUserData);
    }
#endif
}
#endif

bool Artboard::sharesLayoutWithHost() const
{
    return m_host != nullptr && m_host->isLayoutProvider();
}

void Artboard::cloneObjectDataBinds(const Core* object,
                                    Core* clone,
                                    Artboard* artboard) const
{

    for (auto dataBind : dataBinds())
    {
        if (dataBind->target() == object)
        {
            artboard->addDataBind(dataBind->cloneWithTarget(clone));
        }
    }
}

void Artboard::syncInstanceValueBinds()
{
    // Mid update the removes and adds would only queue, and a second change
    // in the same pass could not see them; coalesce until the pass drains.
    if (isProcessingDataBinds())
    {
        m_instanceValueBindsPending = true;
        return;
    }
    auto instance = dataBindContext() != nullptr
                        ? dataBindContext()->mainViewModelInstance()
                        : nullptr;
    if (instance == m_instanceValueBindsSource)
    {
        return;
    }
    // Snapshot: removing mutates the list we are walking.
    auto previous = dataBinds();
    for (auto dataBind : previous)
    {
        if (dataBind->isInstanceValueBind())
        {
            removeAndDeleteDataBind(dataBind);
        }
    }
    m_instanceValueBindsSource = instance;
    if (instance == nullptr)
    {
        return;
    }
    for (auto dataBind : instance->valueDataBinds())
    {
        auto dataBindClone = dataBind->cloneWithTarget(dataBind->target());
        dataBindClone->markInstanceValueBind();
        addDataBind(dataBindClone);
    }
}

void Artboard::mainViewModelInstanceChanged()
{
    wakeIfQuietRow();
    syncInstanceValueBinds();
}

void Artboard::dataContextChanged() { wakeIfQuietRow(); }

void Artboard::wakeQuietRow()
{
    auto row = m_quietHostRow;
    m_quietHostRow = kNoQuietRow;
    if (m_host != nullptr)
    {
        m_host->hostedRowWoke(this, row);
    }
}

AdvancingComponent::QuietState Artboard::rowQuietState()
{
    using QuietState = AdvancingComponent::QuietState;
    // Work this check can't see into: hosted artboards and lists, joysticks,
    // resettables and scripts.
    if (!m_ArtboardHosts.empty() || !m_Joysticks.empty() ||
        !m_Resettables.empty() || !m_ScriptedObjects.empty())
    {
        return QuietState::never;
    }
    // Cheapest first: a busy row is checked again every frame.
    if (hasDirt(ComponentDirt::Components) || !m_dirtyLayout.empty() ||
        m_hostTransformMarkedDirty || m_instanceValueBindsPending ||
        hasDataBindWork())
    {
        return QuietState::busy;
    }
    auto state = QuietState::quiet;
    for (auto advancing : m_advancingComponents)
    {
        switch (advancing->quietState())
        {
            case QuietState::never:
                return QuietState::never;
            case QuietState::busy:
                state = QuietState::busy;
                break;
            case QuietState::quiet:
                break;
        }
    }
    if (state == QuietState::quiet && mayAdvanceDataBinds())
    {
        // Converters that advance can't say whether they would.
        return QuietState::never;
    }
    return state;
}

void Artboard::dataBindsProcessed()
{
    if (m_instanceValueBindsPending)
    {
        m_instanceValueBindsPending = false;
        syncInstanceValueBinds();
    }
}

void Artboard::buildKeyFrameSourceBindsIndex() const
{
    m_keyFrameSourceBindsBuilt = true;
    for (auto dataBind : dataBinds())
    {
        auto target = dataBind->target();
        if (target == nullptr || !target->is<KeyFrame>())
        {
            continue;
        }
        // A keyframe holds a single value, so keep the first bind per target
        // (emplace does not overwrite an existing key).
        m_keyFrameSourceBinds.emplace(target->as<KeyFrame>(), dataBind);
    }
}

bool Artboard::hasKeyFrameSourceBinds() const
{
    if (!m_keyFrameSourceBindsBuilt)
    {
        buildKeyFrameSourceBindsIndex();
    }
    return !m_keyFrameSourceBinds.empty();
}

DataBind* Artboard::keyFrameSourceBind(const KeyFrame* keyframe) const
{
    if (!m_keyFrameSourceBindsBuilt)
    {
        buildKeyFrameSourceBindsIndex();
    }
    auto it = m_keyFrameSourceBinds.find(keyframe);
    return it != m_keyFrameSourceBinds.end() ? it->second : nullptr;
}

void Artboard::host(ArtboardHost* artboardHost)
{
    addedToHost();
    m_host = artboardHost;
#ifdef WITH_RIVE_LAYOUT
    if (!sharesLayoutWithHost())
    {
        return;
    }
    Artboard* parent = parentArtboard();
    if (parent != nullptr)
    {
        parent->markLayoutDirty(this);
        parent->syncLayoutChildren();
    }
#endif
}

ArtboardHost* Artboard::host() const { return m_host; }

StatusCode Artboard::onAddedClean(CoreContext* context)
{
    auto code = Super::onAddedClean(context);
    if (code != StatusCode::Ok)
    {
        return code;
    }
    NodeBase::x(0);
    NodeBase::y(0);
    return StatusCode::Ok;
}

Artboard* Artboard::parentArtboard() const
{
    if (m_host == nullptr)
    {
        return nullptr;
    }
    return m_host->parentArtboard();
}

float Artboard::layoutWidth() const
{
#ifdef WITH_RIVE_LAYOUT
    return m_layout.width();
#else
    return width();
#endif
}

float Artboard::layoutHeight() const
{
#ifdef WITH_RIVE_LAYOUT
    return m_layout.height();
#else
    return height();
#endif
}

float Artboard::layoutX() const
{
#ifdef WITH_RIVE_LAYOUT
    return m_layout.left();
#else
    return 0.0f;
#endif
}

float Artboard::layoutY() const
{
#ifdef WITH_RIVE_LAYOUT
    return m_layout.top();
#else
    return 0.0f;
#endif
}

void Artboard::updateRenderPath()
{
    AABB bg = AABB::fromLTWH(-layoutWidth() * originX(),
                             -layoutHeight() * originY(),
                             layoutWidth(),
                             layoutHeight());
    AABB clip;
    if (m_FrameOrigin)
    {
        clip = {0.0f, 0.0f, layoutWidth(), layoutHeight()};
    }
    else
    {
        clip = bg;
    }
    auto& renderPaths = mutableRenderPaths();
    renderPaths.local.rewind();
    renderPaths.local.addRect(bg);
    renderPaths.world.rewind();
    renderPaths.world.addRect(clip);
}

void Artboard::update(ComponentDirt value)
{
    Super::update(value);
    if (hasDirt(value, ComponentDirt::DrawOrder))
    {
        sortDrawOrder();
    }
    if (hasDirt(value, ComponentDirt::Clipping))
    {
        clearRedundantOperations();
    }
#ifdef WITH_RIVE_LAYOUT
    if (hasDirt(value, ComponentDirt::LayoutStyle))
    {
        bool cascadeChanged = cascadeLayoutStyle(interpolation(),
                                                 interpolator(),
                                                 interpolationTime(),
                                                 actualDirection());
        // TODO: Explore whether we can remove the syncStyleChanges call in
        // updatePass. Since updatePass calls updateComponents, where the first
        // component is the artboard itself, hence calling update, we end up
        // calling this twice. Although it is safe, because syncStyleChanges
        // checks for the list of dirty layouts that would be empty at this
        // point, it seems redundant.
        syncStyleChangesWithUpdate(cascadeChanged);
    }
#endif
    m_hostTransformMarkedDirty = false;
}

void Artboard::addDirtyDataBind(DataBind* dataBind)
{
    wakeIfQuietRow();
    // Most artboard data binds target Components and need the component graph
    // marked dirty. Keyframe value binds instead target transient
    // BindableProperty holders (see
    // LinearAnimationInstance::keyFrameValueHolder) that aren't in the
    // component graph — they're read directly during animation apply — so only
    // propagate component dirt for Component targets.
    auto target = dataBind->target();
    if (target != nullptr && target->is<Component>())
    {
        onComponentDirty(target->as<Component>());
    }
    DataBindContainer::addDirtyDataBind(dataBind);
}

void Artboard::updateDataBinds(bool applyTargetToSource)
{
    for (auto artboardHost : m_ArtboardHosts)
    {
        artboardHost->updateDataBinds();
    }
    DataBindContainer::updateDataBinds(applyTargetToSource);
}

bool Artboard::updateComponents()
{
    if (!hasDirt(ComponentDirt::Components))
    {
        return false;
    }
    const int maxSteps = 100;
    int step = 0;
    auto count = m_DependencyOrder.size();
    while (hasDirt(ComponentDirt::Components) && step < maxSteps)
    {
        m_Dirt = m_Dirt & ~ComponentDirt::Components;

        // Track dirt depth here so that if something else marks
        // dirty, we restart.
        for (unsigned int i = 0; i < count; i++)
        {
            auto component = m_DependencyOrder[i];
            m_DirtDepth = i;
            auto d = component->m_Dirt;
            if (d == ComponentDirt::None ||
                (d & ComponentDirt::Collapsed) == ComponentDirt::Collapsed)
            {
                continue;
            }
            component->m_Dirt = ComponentDirt::None;
            component->update(d);

            // If the update changed the dirt depth by adding dirt
            // to something before us (in the DAG), early out and
            // re-run the update.
            if (m_DirtDepth < i)
            {
                break;
            }
        }
        step++;
    }
    return true;
}

LayoutData* Artboard::takeLayoutData()
{
#ifdef WITH_RIVE_LAYOUT
    m_updatesOwnLayout = false;
    return m_layoutData;
#else
    return nullptr;
#endif
}

void Artboard::cleanLayout(LayoutComponent* layoutComponent)
{
    assert(!m_isCleaningDirtyLayouts);
    if (m_isCleaningDirtyLayouts)
    {
        fprintf(stderr,
                "Artboard::cleanLayout - trying to remove a dirty layout "
                "during clean pass!\n");
        return;
    }

    if (!m_dirtyLayout.empty())
    {
        auto itr = m_dirtyLayout.find(layoutComponent);
        if (itr != m_dirtyLayout.end())
        {
            m_dirtyLayout.erase(itr);
        }
    }
    // If we called cleanLayout on ourselves, make sure to also
    // call it on our parent artboard in case we were dirtied
    if (layoutComponent == this)
    {
        Artboard* parent = parentArtboard();
        if (parent != nullptr)
        {
            parent->cleanLayout(layoutComponent);
        }
    }
}

void Artboard::markLayoutDirty(LayoutComponent* layoutComponent)
{
    wakeIfQuietRow();
    assert(!m_isCleaningDirtyLayouts);
    if (m_isCleaningDirtyLayouts)
    {
        fprintf(stderr,
                "Artboard::markLayoutDirty - trying to mark a layout dirty "
                "during clean pass!\n");
        return;
    }
#ifdef WITH_RIVE_TOOLS
    if (m_dirtyLayout.empty() && m_layoutDirtyCallback != nullptr)
    {
        m_layoutDirtyCallback(callbackUserData);
    }
#endif
    m_dirtyLayout.insert(layoutComponent);
    if (isInstance())
    {
        if (sharesLayoutWithHost())
        {
            m_host->markHostingLayoutDirty(this->as<ArtboardInstance>());
        }
        else
        {
            markHostTransformDirty();
        }
    }
    addDirt(ComponentDirt::Components);
}

void Artboard::markHostTransformDirty()
{
    wakeIfQuietRow();
#ifdef WITH_RIVE_TOOLS
    if (!m_hostTransformMarkedDirty && m_transformDirtyCallback != nullptr)
    {
        m_transformDirtyCallback(callbackUserData);
    }
#endif
    m_hostTransformMarkedDirty = true;
    if (host())
    {
        host()->markHostTransformDirty();
    }
}

void Artboard::syncStyleChangesWithUpdate(bool forceUpdate)
{
#ifdef WITH_RIVE_LAYOUT
    if (syncStyleChanges() && (m_updatesOwnLayout || forceUpdate))
    {
        calculateLayout();
        updateLayoutBounds(/*animation*/ true); // maybe use a static to allow
                                                // the editor to set this.
    }
#endif
}

bool Artboard::syncStyleChanges()
{
    bool updated = false;
    m_isCleaningDirtyLayouts = true;
#ifdef WITH_RIVE_LAYOUT
    if (!m_dirtyLayout.empty())
    {
        for (auto layout : m_dirtyLayout)
        {
            if (layout == nullptr)
            {
                continue;
            }
            switch (layout->coreType())
            {
                case ArtboardBase::typeKey:
                {
                    auto artboard = layout->as<Artboard>();
                    if (artboard == this)
                    {
                        artboard->syncStyle();
                    }
                    else
                    {
                        // This is a nested artboard, sync its changes too.
                        if (!artboard->updatesOwnLayout())
                        {
                            artboard->syncStyleChanges();
                        }
                    }
                    break;
                }

                default:
                    layout->syncStyle();
                    break;
            }
        }
        m_dirtyLayout.clear();
        updated = true;
    }
#endif
    m_isCleaningDirtyLayouts = false;
    return updated;
}

void Artboard::calculateLayout()
{
    // Always pass NAN and let calculateLayoutInternal decide whether to use
    // the intrinsic (hug) size or fall back to width()/height().
    //
    // This covers all cases:
    // - Runtime:
    //   - Top level artboards: intrinsically sized artboards get NAN so Yoga
    //     computes from children; fixed-size artboards fall back to
    //     width()/height() inside calculateLayoutInternal.
    //   - Nested node/leaf artboards (m_updatesOwnLayout == true): same as
    //     top-level, calculateLayoutInternal handles the distinction.
    //   - Nested layout-mode artboards (NestedArtboardLayout): their layout
    //     node is owned by the parent via takeLayoutData(), which sets
    //     m_updatesOwnLayout = false. syncStyleChangesWithUpdate() gates on
    //     that flag, so calculateLayout() is not reached for these.
    // - Editor:
    //   - Top level artboards: are handled on the Dart side so don't take
    //     this code path
    //   - Nested node/leaf artboards (m_updatesOwnLayout == true):
    //     same as runtime, calculateLayoutInternal handles the distinction.
    //   - Nested layout-mode artboards (NestedArtboardLayout): same
    //     as runtime, their layout node is owned by the Dart parent
    //     which sets m_updatesOwnLayout = false
#ifdef TESTING
    sm_layoutPassCount++;
#endif
    calculateLayoutInternal(NAN, NAN);
}

bool Artboard::updatePass(bool isRoot)
{
    RIVE_PROF_SCOPE()
    updateDataBinds();
    bool didUpdate = false;
    syncStyleChangesWithUpdate();
    m_hostTransformMarkedDirty = false;

    if (m_JoysticksApplyBeforeUpdate)
    {
        for (auto joystick : m_Joysticks)
        {
            joystick->apply(this);
        }
    }
    if (updateComponents())
    {
        didUpdate = true;
    }
    if (!m_JoysticksApplyBeforeUpdate)
    {
        for (auto joystick : m_Joysticks)
        {
            if (!joystick->canApplyBeforeUpdate())
            {
                updateDataBinds();
                if (updateComponents())
                {
                    didUpdate = true;
                }
            }
            joystick->apply(this);
        }
        updateDataBinds();
        if (updateComponents())
        {
            didUpdate = true;
        }
    }
    if (didUpdate)
    {
        updateDataBinds();
    }
    return didUpdate;
}

bool Artboard::advanceInternal(float elapsedSeconds, AdvanceFlags flags)
{
    RIVE_PROF_SCOPE()
    bool didUpdate = false;

    for (auto adv : m_advancingComponents)
    {
        if (adv->advanceComponent(elapsedSeconds, flags))
        {
            didUpdate = true;
        }
    }
    if (advanceDataBinds(elapsedSeconds))
    {
        didUpdate = true;
    }

    return didUpdate;
}

void Artboard::reset()
{
    if (m_Resettables.size() == 0)
    {
        return;
    }
    for (auto obj : m_Resettables)
    {
        obj->reset();
    }
}

bool Artboard::advance(float elapsedSeconds, AdvanceFlags flags)
{
    // Poll async work (image decodes, etc.) so promises resolve before
    // script advance() callbacks run.
    pollAsyncWork();

    AdvanceFlags advancingFlags = flags;
    advancingFlags |= AdvanceFlags::IsRoot;
    bool didUpdate = advanceInternal(elapsedSeconds, advancingFlags);
    if (updatePass(true))
    {
        didUpdate = true;
    }
    return didUpdate || hasDirt(ComponentDirt::Components);
}

Core* Artboard::hitTest(HitInfo* hinfo, const Mat2D& xform)
{
    if (clip())
    {
        // TODO: can we get the rawpath for the clip?
    }

    auto mx = xform;
    if (m_FrameOrigin)
    {
        mx *= Mat2D::fromTranslate(layoutWidth() * originX(),
                                   layoutHeight() * originY());
    }
    // Mirror drawInternal's own rotation/scale so hit-testing matches what is
    // drawn. This single spot also covers nested instances, since
    // NestedArtboard::hitTest re-enters Artboard::hitTest.
    if (hasSelfTransform())
    {
        mx *= selfTransform();
    }

    Drawable* last = m_FirstDrawable;
    if (last)
    {
        // walk to the end, so we can visit in reverse-order
        while (last->prev)
        {
            last = last->prev;
        }
    }
    for (auto drawable = last; drawable; drawable = drawable->next)
    {
        if (drawable->isHidden())
        {
            continue;
        }
        if (auto c = drawable->hitTest(hinfo, mx))
        {
            return c;
        }
    }

    // TODO: should we hit-test the background?

    return nullptr;
}

Vec2D Artboard::rootTransform(const Vec2D& point)
{
    // When this artboard is nested, its own rotation/scale (applied about the
    // origin at draw time) is part of how its contents land in the parent, so
    // fold it in before mapping through the host. Top-level artboards are the
    // root coordinate space, so their own transform is not applied here.
    if (host())
    {
        auto local = hasSelfTransform() ? selfTransform() * point : point;
        return host()->hostTransformPoint(local, this->as<ArtboardInstance>());
    }
#ifdef WITH_RIVE_TOOLS
    // Editor artboards don't have a host, so we expose a function that calls
    // the host in dart. The callback is only wired up for mounted (nested)
    // instances, so applying the self transform here matches the host() path.
    if (m_rootTransformCallback != nullptr)
    {
        auto local = hasSelfTransform() ? selfTransform() * point : point;
        auto x =
            m_rootTransformCallback(callbackUserData, local.x, local.y, true);
        auto y =
            m_rootTransformCallback(callbackUserData, local.x, local.y, false);
        return Vec2D(x, y);
    }
#endif
    return point;
}

bool Artboard::hitTestPoint(const Vec2D& position,
                            bool skipOnUnclipped,
                            bool isPrimaryHit)
{
    if (host() != nullptr && isInstance())
    {
        if (!host()->hitTestHost(position,
                                 skipOnUnclipped,
                                 this->as<ArtboardInstance>()))
        {
            return false;
        }
    }
#ifdef WITH_RIVE_TOOLS
    // Editor artboards don't have a host, so we expose a function that calls
    // the host in dart.
    if (m_testBoundsCallback != nullptr)
    {
        // Dart can't return booleans to cpp, so we use a uint_8 instead
        auto didHit = m_testBoundsCallback(callbackUserData,
                                           position.x,
                                           position.y,
                                           skipOnUnclipped);
        if (didHit == 0)
        {
            return false;
        }
    }
#endif
    return LayoutComponent::hitTestPoint(position,
                                         skipOnUnclipped,
                                         isPrimaryHit);
}

void Artboard::watermark(std::unique_ptr<Watermark> watermark)
{
    m_watermark = std::move(watermark);
}

bool Artboard::advanceWatermark(float elapsedSeconds)
{
    if (m_watermark == nullptr)
    {
        return false;
    }
    if (!m_watermark->advance(elapsedSeconds))
    {
        m_watermark = nullptr;
        return false;
    }
    return true;
}

void Artboard::draw(Renderer* renderer)
{
    sm_frameId++;
    // Nested artboards and component lists draw through drawInternal, so only a
    // top level draw can be diverted to the watermark. isPlaying() keeps an
    // artboard that is never advanced through a state machine (and so never
    // starts its watermark) drawing itself rather than freezing on a pre-roll
    // that would never end.
    if (m_watermark != nullptr && m_watermark->isPlaying())
    {
        m_watermark->draw(renderer, bounds());
        return;
    }
    // A standalone/root artboard is never cached as a bitmap: it is already the
    // top-level render target, and a host can skip drawing entirely via
    // didChange(). Only nested/instanced draws (which reach drawInternal
    // directly) participate in cache-as-bitmap.
    drawContent(renderer);
}

struct ModulatedDraw
{
    uint32_t propertyKey;
    // Alpha, red, green, blue of the tags above, multiplied in float so
    // depth does not round.
    std::array<float, 4> level = {1.0f, 1.0f, 1.0f, 1.0f};
};

static void modulatedDrawVisitor(void* context,
                                 Drawable* drawable,
                                 Renderer* renderer)
{
    auto modulated = static_cast<ModulatedDraw*>(context);
    auto property = drawable->customProperty(modulated->propertyKey);
    std::array<float, 4> own;
    if (property != nullptr && property->is<CustomPropertyNumber>())
    {
        float value =
            math::clamp(property->as<CustomPropertyNumber>()->propertyValue(),
                        0.0f,
                        1.0f);
        own = {1.0f, value, value, value};
    }
    else if (property != nullptr && property->is<CustomPropertyColor>())
    {
        ColorInt color = property->as<CustomPropertyColor>()->propertyValue();
        own = {colorOpacity(color),
               colorRed(color) / 255.0f,
               colorGreen(color) / 255.0f,
               colorBlue(color) / 255.0f};
    }
    else
    {
        // Tagged, but not with this key.
        drawable->draw(renderer);
        return;
    }
    std::array<float, 4> outer = modulated->level;
    unsigned int channels[4];
    for (size_t i = 0; i < own.size(); i++)
    {
        modulated->level[i] = outer[i] * own[i];
        channels[i] = (unsigned int)std::lround(modulated->level[i] * 255.0f);
    }
    renderer->modulateColor(
        colorARGB(channels[0], channels[1], channels[2], channels[3]),
        true);
    drawable->draw(renderer);
    modulated->level = outer;
}

void Artboard::drawModulated(Renderer* renderer,
                             uint32_t propertyKey,
                             const File* keysFile)
{
    ModulatedDraw modulated = {propertyKey};
    drawInternal(renderer, modulatedDrawVisitor, &modulated, keysFile);
}

const File* Artboard::drawVisitorFile() const
{
    return m_drawVisitorFile != nullptr ? m_drawVisitorFile
                                        : artboardFile().get();
}

void Artboard::drawHosted(Artboard* hosted, Renderer* renderer)
{
    DrawVisitor visitor = m_drawVisitor;
    if (visitor != nullptr)
    {
        // Name ids are per file, so a key means nothing in an artboard bound
        // in from another one.
        const File* file = drawVisitorFile();
        const File* hostedFile = hosted->artboardFile().get();
        if (hostedFile != nullptr && hostedFile != file)
        {
            visitor = nullptr;
        }
        hosted->m_drawVisitorFile = file;
    }
    hosted->drawInternal(renderer, visitor, m_drawVisitorContext);
}

void Artboard::drawInternal(Renderer* renderer,
                            DrawVisitor visitor,
                            void* visitorContext,
                            const File* keysFile)
{
    if (keysFile != nullptr)
    {
        m_drawVisitorFile = keysFile;
    }
#ifdef RIVE_CANVAS
    // A cached bitmap has no drawables left to visit.
    if (visitor == nullptr && m_BitmapCache != nullptr &&
        drawCachedAsBitmap(renderer))
    {
        return;
    }
#endif
    drawContent(renderer, visitor, visitorContext);
}

void Artboard::drawContent(Renderer* renderer,
                           DrawVisitor visitor,
                           void* visitorContext)
{
    RIVE_PROF_SCOPE_L(1)
    m_didChange = false;
    if (childOpacity() == 0)
    {
        return;
    }
    // Hosted artboards read these while this draw runs. A draw started from
    // inside a visit hands them back, and none outlives its context.
    struct VisitorScope
    {
        Artboard* artboard;
        DrawVisitor visitor;
        void* context;
        ~VisitorScope()
        {
            artboard->m_drawVisitor = visitor;
            artboard->m_drawVisitorContext = context;
        }
    } visitorScope{this, m_drawVisitor, m_drawVisitorContext};
    m_drawVisitor = visitor;
    m_drawVisitorContext = visitorContext;
    bool hasSelf = hasSelfTransform();
    bool save = clip() || m_FrameOrigin || hasSelf;
    if (save)
    {
        renderer->save();
    }

    if (m_FrameOrigin)
    {
        Mat2D artboardTransform;
        artboardTransform[4] = layoutWidth() * originX();
        artboardTransform[5] = layoutHeight() * originY();
        renderer->transform(artboardTransform);
    }

    // Apply the artboard's own rotation/scale, pivoted around its origin.
    // Content-local (0,0) is the origin anchor, so this is simply rotation *
    // scale with no extra pivot translation. Applied after the frame-origin
    // translation so the anchor stays put, and it covers both top-level and
    // nested (mounted) rendering since both funnel through drawInternal.
    // Hit-testing mirrors this via selfTransform() so interaction matches.
    if (hasSelf)
    {
        renderer->transform(selfTransform());
    }

    // Clip after the frame-origin and self transforms so the clip region tracks
    // the (possibly rotated/scaled) artboard. The local path is the
    // content-local bounds, so it is transformed along with the content.
    if (clip())
    {
        renderer->clipPath(mutableRenderPaths().local.renderPath(this));
    }

    for (auto shapePaint : m_ShapePaints)
    {
        if (!shapePaint->shouldDraw())
        {
            continue;
        }
        auto shapePaintPath = shapePaint->pickPath(this);
        if (shapePaintPath == nullptr)
        {
            continue;
        }
        shapePaint->draw(renderer, shapePaintPath, worldTransform());
    }
    drawDrawableRange(renderer, m_FirstDrawable, nullptr);
    if (save)
    {
        renderer->restore();
    }
}

void Artboard::drawDrawableRange(Renderer* renderer,
                                 Drawable* first,
                                 Drawable* stop)
{
    // Empty clips is a counter for clipping shapes that are empty, for
    // example because they are hidden in a solo. If emptyClips > 0, the
    // drawables should not be drawn. A layer mask's source bracket rides the
    // same counter to suppress the source in the normal pass.
    int emptyClips = 0;
    // We stack clip operations to avoid calling a save + clip + restore on
    // clipping that don't have any drawables in between. this is a common
    // case with drawables in solos where the drawables are not drawn.
    // Deliberately a local: this function recurses through drawMasked.
    std::vector<Drawable*> pendingClipOperations;
    for (auto drawable = first; drawable != stop; drawable = drawable->prev)
    {
        auto prevClips = emptyClips;
        emptyClips += drawable->emptyClipCount();
        if (!drawable->willDraw() || emptyClips != prevClips || emptyClips > 0)
        {
            continue;
        }
        if (drawable->isClipStart())
        {
            pendingClipOperations.push_back(drawable);
            continue;
        }
        else if (pendingClipOperations.size() > 0)
        {
            // If there are clip operations pending and the next drawable is
            // a clip end, the clipping operation does not clip anything and
            // both can be skipped.
            if (drawable->isClipEnd())
            {
                pendingClipOperations.pop_back();
                continue;
            }
            else
            {
                for (auto& pendingClip : pendingClipOperations)
                {
                    pendingClip->draw(renderer);
                }
                pendingClipOperations.clear();
            }
        }
        if (drawable->isMaskStart())
        {
            // Pending clips have already been flushed above, so the ancestor
            // clips are live on `renderer` and will constrain the composite.
            auto* startMarker = static_cast<LayerMaskProxyDrawable*>(drawable);
            Drawable* end = startMarker->pairedEnd();
            if (drawMasked(renderer, startMarker, end))
            {
                // Consumed: skip to the closing marker. `continue` runs the
                // for-increment, so the next iteration starts at end->prev.
                drawable = end;
            }
            // Otherwise fall through and let the range draw inline; the marker
            // itself draws nothing either way.
            continue;
        }
        if (drawable->isMaskEnd())
        {
            continue;
        }
        if (m_drawVisitor != nullptr && drawable->hasCustomProperties())
        {
            // Whatever the visitor sets on the renderer ends with the visit.
            renderer->save();
            m_drawVisitor(m_drawVisitorContext, drawable, renderer);
            renderer->restore();
        }
        else
        {
            drawable->draw(renderer);
        }
    }
}

#ifdef RIVE_CANVAS
namespace
{
// How much to pad a drawable that reported `approximate` bounds. Generous on
// purpose: the mask box is intersected with the artboard's own bounds, so the
// worst case of an over-wide margin is a raster no bigger than the one this
// whole change replaces -- while the worst case of an under-wide one is a hard
// crop through the middle of someone's artwork.
constexpr float kApproximateSlopDevicePx = 8.0f;
constexpr float kApproximateSlopFraction = 0.25f;

AABB padApproximate(const AABB& box, float rasterScale)
{
    const float relative =
        kApproximateSlopFraction * std::max(box.width(), box.height());
    const float absolute = rasterScale > 0.0f
                               ? kApproximateSlopDevicePx / rasterScale
                               : kApproximateSlopDevicePx;
    const float slop = std::max(relative, absolute);
    if (!std::isfinite(slop) || slop <= 0.0f)
    {
        return box;
    }
    return box.outset(slop, slop);
}

// Float AABB has no intersect helper, and AABB::overlaps is wrong (it compares
// maxX against b.minY), so this is written out. False for an empty result.
bool intersectBoxes(const AABB& a, const AABB& b, AABB* out)
{
    const AABB r(std::max(a.left(), b.left()),
                 std::max(a.top(), b.top()),
                 std::min(a.right(), b.right()),
                 std::min(a.bottom(), b.bottom()));
    if (r.isEmptyOrNaN())
    {
        return false;
    }
    *out = r;
    return true;
}
} // namespace

BoundsFidelity Artboard::rangeDrawBounds(Drawable* first,
                                         Drawable* stop,
                                         float rasterScale,
                                         AABB* out,
                                         bool* anyDrawn) const
{
    // The skip rules mirror drawDrawableRange deliberately, which is what buys
    // the awkward cases for free: a drawable inside a nested empty clip is
    // excluded, and so is a nested mask's source range -- its markers push the
    // same empty-clip counter -- while a nested mask's own members are
    // included, which is correct because a mask only ever attenuates what is
    // already there.
    int emptyClips = 0;
    AABB accumulated = AABB::forExpansion();
    BoundsFidelity worst = BoundsFidelity::exact;
    bool drew = false;

    for (auto* d = first; d != stop; d = d->prevDrawable())
    {
        const int prevClips = emptyClips;
        emptyClips += d->emptyClipCount();
        if (!d->willDraw() || emptyClips != prevClips || emptyClips > 0)
        {
            continue;
        }
        // Bracket markers paint nothing of their own: a clip only constrains
        // what follows it, and a mask marker is consumed by drawMasked.
        if (d->isClipStart() || d->isClipEnd() || d->isMaskStart() ||
            d->isMaskEnd())
        {
            continue;
        }
        drew = true;

        AABB painted;
        const BoundsFidelity fidelity = d->paintedWorldBounds(&painted);
        if (fidelity == BoundsFidelity::none)
        {
            // Not "pad it harder": there is no measurement to pad. Give up on a
            // tight box for this range rather than inventing one.
            *anyDrawn = true;
            return BoundsFidelity::none;
        }
        if (fidelity == BoundsFidelity::approximate)
        {
            worst = BoundsFidelity::approximate;
            painted = padApproximate(painted, rasterScale);
        }
        // A drawable can legitimately paint nothing -- a shape whose paths all
        // collapsed reports an empty box. Filtering here also keeps
        // AABB::forExpansion()'s +/-FLT_MAX sentinel out of the union.
        if (!painted.isEmptyOrNaN())
        {
            accumulated.expand(painted);
        }
    }

    *anyDrawn = drew;
    if (!drew)
    {
        return BoundsFidelity::exact;
    }
    if (accumulated.isEmptyOrNaN())
    {
        // Something drew but nothing measurable came of it. Rare, and not worth
        // reasoning about further: fall back.
        return BoundsFidelity::none;
    }
    *out = accumulated;
    return worst;
}

bool Artboard::drawMasked(Renderer* renderer,
                          Drawable* startMarker,
                          Drawable* endMarker)
{
    LayerMask& mask =
        *static_cast<LayerMaskProxyDrawable*>(startMarker)->mask();
    if (!mask.isVisible())
    {
        return false;
    }

    // Re-entry guard, and defence in depth rather than a fix for anything
    // reachable today.
    //
    // onAddedClean rejects a mask whose source sits under its own parent, which
    // only catches a mask pointing at itself. Two masks naming each other's
    // subtrees pass that test, and the coverage pass draws a RANGE that
    // drawDrawableRange dispatches from, so in principle A could rasterize B
    // which rasterizes A without bound.
    //
    // In practice spliceLayerMaskBracket grows every range outward until it is
    // balanced with the brackets already in the list, so brackets nest and
    // never interleave: if B's members sit inside A's source bracket, B's range
    // grows to enclose the whole of A, which puts A's source range INSIDE B
    // rather than the other way round, and walking it never reaches B's start
    // marker. A mutual pair therefore terminates today -- there is a
    // [layer-mask] test pinning exactly that -- and this costs a bool and a
    // branch against the day the nesting invariant is relaxed, or a longer
    // cycle is reached some other way.
    //
    // Per mask, so legitimate nesting -- a different LayerMask inside a masked
    // subtree -- is unaffected.
    if (mask.m_isDrawing)
    {
        return false;
    }
    // Cleared however this returns, and there are many exits below.
    struct DrawingGuard
    {
        LayerMask& mask;
        DrawingGuard(LayerMask& m) : mask(m) { mask.m_isDrawing = true; }
        ~DrawingGuard() { mask.m_isDrawing = false; }
    } drawingGuard(mask);

    // canvasContentHost, not deferredCanvasHost: this only needs somewhere to
    // rasterize into. No host means nobody can give us an offscreen frame (a
    // plain non-GPU or test factory), so the content draws unmasked -- the
    // permanent fallback, and the reason a mask degrades rather than vanishing.
    Factory* f = factory();
    auto* host = f ? f->canvasContentHost() : nullptr;
    if (host == nullptr)
    {
        return false;
    }

    // The same fallback, one step earlier, for a host that can rasterize but
    // cannot apply the mask. Renderer::applyLayerMask already no-ops there, but
    // finding out that late is too late: the rasters below are sized to the
    // content-and-coverage intersection, so the layer would come back unmasked
    // and *cropped* to a box that only made sense if the mask had been applied.
    // Bailing here draws the range inline -- unmasked for real, and two
    // canvases and a composite cheaper.
    if (!host->supportsLayerMask())
    {
        return false;
    }

    // The raster scale before anything is measured: it depends only on the
    // renderer's transform, and it is the unit the slop margin for an
    // approximately-bounded drawable is expressed against.
    offscreen::RasterPlan plan;
    if (!offscreen::planRasterScale(renderer, mask.resolution(), &plan))
    {
        return false;
    }

    // mask.m_dirty alone. LayerMask sits on the dependency graph as a dependent
    // of everything in its own range and its own source, so its update() raises
    // this when -- and only when -- something it actually rasterizes changed.
    //
    // This used to also read the artboard-wide "something moved" flag, which
    // meant every mask re-rasterized both of its canvases whenever anything
    // anywhere in the artboard moved, however unrelated. That flag was captured
    // into a separate field just for this read, and both are now gone.
    const bool contentChanged = mask.m_contentCanvas == nullptr ||
                                mask.m_maskCanvas == nullptr || mask.m_dirty;

    AABB tight;
    if (contentChanged)
    {
        // Measuring both ranges also answers "would anything draw at all",
        // which is what the two cheap probes that used to live here did on
        // their own.
        bool contentDraws = false;
        AABB contentBox;
        const BoundsFidelity contentFidelity =
            rangeDrawBounds(startMarker->prevDrawable(),
                            endMarker,
                            plan.rasterScale,
                            &contentBox,
                            &contentDraws);
        if (!contentDraws)
        {
            // Nothing in the range would have drawn, so consume the bracket
            // rather than rasterizing two empty textures.
            return true;
        }

        bool coverageDraws = false;
        AABB sourceBox;
        BoundsFidelity sourceFidelity = BoundsFidelity::none;
        if (mask.sourceStart() == nullptr)
        {
            // No source bracket. Two very different situations arrive here and
            // the mode-switch below is only right for one of them.
            //
            // interleaveLayerMasks splices the masked range first and the
            // source second, and the second can fail on its own -- a draw rule
            // can scatter the source subtree so it is not contiguous. The
            // masked bracket is already in the list by then, so this mask is
            // live with no source bracket, and the source subtree is NOT
            // suppressed: it draws in its natural position. Treating coverage
            // as absent would erase the whole masked range in alpha/luminance
            // while the mask art itself stayed on screen -- the content gone
            // and the mask visible, which is the worst of both.
            //
            // So only take the empty-coverage path when the source genuinely
            // draws nothing. If anything in it would draw, the bracket is the
            // thing that is missing, and the mask goes inert: return false and
            // the range draws inline, unmasked.
            for (Drawable* d : mask.sourceDrawables())
            {
                if (d->willDraw())
                {
                    return false;
                }
            }
        }
        else
        {
            // Over the source bracket rather than sourceDrawables(), matching
            // what the coverage pass below actually draws -- so a clipping
            // shape nested inside the source is accounted for the same way.
            sourceFidelity = rangeDrawBounds(mask.sourceStart()->prevDrawable(),
                                             mask.sourceEnd(),
                                             plan.rasterScale,
                                             &sourceBox,
                                             &coverageDraws);
        }
        if (!coverageDraws)
        {
            // Coverage is zero everywhere -- the mask source is hidden, or sits
            // in an inactive solo. Which way that falls depends on the mode,
            // and both answers avoid the GPU entirely.
            switch (mask.maskMode())
            {
                case MaskMode::alpha:
                case MaskMode::luminance:
                    return true; // content fully masked out
                case MaskMode::invertedAlpha:
                case MaskMode::invertedLuminance:
                    return false; // content fully visible; draw it inline
            }
        }

        // One box and one scale for both canvases, so a content texel and a
        // coverage texel at the same coordinate correspond with no resampling
        // and no second transform.
        bool authoredBox = false;
        const AABB authored = mask.customBounds();
        if (mask.useCustomBounds() && !authored.isEmptyOrNaN())
        {
            // The author drew this rectangle, in artboard space. Taken
            // verbatim: no slop margin, and deliberately no intersect with the
            // artboard box either, because cropping a mask to a region that
            // reaches outside the artboard is intent rather than an error.
            // kMaxDim still caps it.
            //
            // The ranges above were still walked, which is what keeps the
            // "nothing draws" and "no coverage" shortcuts working; only the box
            // comes from here. The mode-aware intersect is skipped on purpose
            // -- the author has already said which region matters.
            //
            // A degenerate rectangle -- zero or negative extent, which is what
            // a half-drawn one looks like -- falls through to measuring rather
            // than collapsing the raster and dropping the layer.
            tight = authored;
            authoredBox = true;
        }
        else if (contentFidelity == BoundsFidelity::none)
        {
            // Something in the range could not say where it paints. Fall back
            // to the box that is always big enough.
            tight = bounds();
        }
        else
        {
            tight = contentBox;
            // In the un-inverted modes the coverage texel is zero outside the
            // source, so content out there is erased anyway: intersecting costs
            // nothing and it is where the win lives, because a small mask over
            // a full-stage layer now rasterizes only the small mask. The
            // inverted modes are the opposite -- absent coverage means a factor
            // of 1, so the content box has to stand on its own.
            const bool intersectsSource =
                mask.maskMode() == MaskMode::alpha ||
                mask.maskMode() == MaskMode::luminance;
            if (sourceFidelity != BoundsFidelity::none)
            {
                // sourceBox is a superset of where coverage actually lands, so
                // "these do not overlap" is a claim that holds: no coverage
                // reaches the content at all.
                AABB overlap;
                const bool overlaps =
                    intersectBoxes(tight, sourceBox, &overlap);
                if (intersectsSource)
                {
                    if (!overlaps)
                    {
                        // Every content texel would be multiplied by zero
                        // coverage. Consume the bracket and draw nothing at
                        // all.
                        return true;
                    }
                    tight = overlap;
                }
                else if (!overlaps)
                {
                    // Inverted, so absent coverage means a factor of one: the
                    // layer is fully visible. Decline the bracket and let it
                    // draw inline, exactly as a source that draws nothing at
                    // all does.
                    return false;
                }
            }
        }

        // Clamped to the artboard only when the artboard actually clips.
        //
        // When it does, content reaching past the edge is cropped at composite
        // time anyway, so rasterizing it would be wasted texels -- and the
        // clamp keeps the raster no larger than the artboard-sized one this
        // replaced, which is what makes the common case monotone: kMaxDim's
        // coarsening can only bite less than before, never more.
        //
        // When it does not clip, that content is genuinely visible, and
        // clamping would crop it inside the mask while it draws fine everywhere
        // else. The artboard-sized rasters had that bug too; this is where it
        // is fixed.
        //
        // The cost is that the monotone guarantee does not hold for an
        // unclipped artboard whose content sprawls far past it: a bigger box
        // can hit kMaxDim and coarsen. Blurrier beats cropped.
        //
        // Skipped entirely for an authored box, where reaching outside the
        // artboard is a decision rather than an accident.
        if (!authoredBox && clip() && !intersectBoxes(tight, bounds(), &tight))
        {
            return false;
        }
    }
    else
    {
        // Nothing changed, so re-measuring would land in the same place. Re-fit
        // the box that was measured, never the box that was fitted -- feeding a
        // fitted box back through the guard band would grow the raster a few
        // texels on every frame.
        tight = mask.m_tightBox;
    }

    // A guard band of transparent texels on every side. Without it the content
    // reaches the raster edge, and the composite's LinearClamp then replicates
    // that edge texel outward under rotation: a one-texel smear along the seam.
    // It is added after the artboard clamp above, so the band can sit a couple
    // of texels outside the artboard -- where the composite is itself clipped
    // when the artboard clips, and where showing those texels is the more
    // correct answer when it does not.
    constexpr uint32_t kGuardTexels = 2;
    if (!offscreen::fitRasterToBox(tight,
                                   kGuardTexels,
                                   offscreen::RasterFit::stableGrid,
                                   &plan))
    {
        return false;
    }

    // Growth is immediate, shrinking waits. Anything rotating or scaling
    // changes the size of its own bounding box every frame, and re-allocating
    // two GPU textures that often costs far more than carrying one bucket of
    // slack.
    const offscreen::RasterResize resize =
        offscreen::decideRasterResize(plan.widthPx,
                                      plan.heightPx,
                                      mask.m_widthPx,
                                      mask.m_heightPx,
                                      &mask.m_shrinkStreak);
    // Hold whatever allocation was settled on, growing the box right and bottom
    // to span it so the composite's inverse still maps exactly onto the pixels.
    offscreen::holdRasterAllocation(resize.widthPx, resize.heightPx, &plan);

    // New textures hold nothing, and the cap inside fitRasterToBox can lower
    // the scale out from under a cached raster, so either forces a rebuild even
    // on a frame that had decided it could reuse what it had.
    const bool mustRaster = contentChanged || resize.reallocate ||
                            plan.rasterScale != mask.m_rasterScale;

    if (mustRaster)
    {
        if (resize.reallocate || mask.m_contentCanvas == nullptr ||
            mask.m_maskCanvas == nullptr)
        {
            mask.m_contentCanvas =
                host->makeContentCanvas(plan.widthPx, plan.heightPx);
            mask.m_maskCanvas =
                host->makeContentCanvas(plan.widthPx, plan.heightPx);
#ifdef TESTING
            mask.testAllocations++;
#endif
        }
        if (mask.m_contentCanvas == nullptr || mask.m_maskCanvas == nullptr)
        {
            mask.releaseCanvases();
            return false;
        }

        // Sequentially, never nested: DeferredSession::endCanvasContent routes
        // back to the screen rather than to an enclosing canvas, so an inner
        // bracket closing inside an outer one would misroute the rest of the
        // outer content. Finishing the coverage canvas before opening the
        // content one keeps the recorded stream two independent segments.
        bool opened = true;
        {
            offscreen::CanvasContentScope scope(host,
                                                mask.m_maskCanvas.get(),
                                                plan,
                                                0);
            if (Renderer* r = scope.renderer())
            {
                // Over the source bracket, not sourceDrawables() directly, so a
                // clipping shape nested inside the source still brackets its
                // own drawables. Starting past the opening marker keeps its
                // own +1 suppression from hiding the very range we want.
                drawDrawableRange(r,
                                  mask.sourceStart()->prevDrawable(),
                                  mask.sourceEnd());
            }
            else
            {
                opened = false;
            }
        }
        if (opened)
        {
            offscreen::CanvasContentScope scope(host,
                                                mask.m_contentCanvas.get(),
                                                plan,
                                                0);
            if (Renderer* r = scope.renderer())
            {
                drawDrawableRange(r, startMarker->prevDrawable(), endMarker);
                // The mask apply has to be the last draw into this canvas: it
                // multiplies everything already there, so anything drawn after
                // it would land unmasked. Issued in the canvas's own pixel
                // space (the scope's transform is still in effect, so undo it)
                // because the coverage texture is the same size as the target
                // and has to line up texel for texel.
                if (rcp<RenderImage> coverage =
                        host->contentCanvasImage(mask.m_maskCanvas.get()))
                {
                    r->save();
                    const float inv = 1.0f / plan.rasterScale;
                    r->translate(plan.box.left(), plan.box.top());
                    r->transform(Mat2D::fromScale(inv, inv));
                    r->applyLayerMask(
                        coverage.get(),
                        ImageSampler::LinearClamp(),
                        static_cast<LayerMaskMode>(mask.maskMode()));
                    r->restore();
                }
            }
            else
            {
                opened = false;
            }
        }
        if (!opened)
        {
            // The host could not open an offscreen frame. Nothing was drawn, so
            // drop the canvases and stay dirty: a later frame retries, and in
            // the meantime the content draws unmasked rather than as a hole.
            mask.releaseCanvases();
            mask.m_dirty = true;
            return false;
        }

        // Commit what the pixels now are. m_tightBox is what a later frame
        // re-fits from; m_box is where these pixels live, which is what the
        // composite has to place them at even after the plan moves on.
        mask.m_tightBox = tight;
        mask.m_box = plan.box;
        mask.m_widthPx = plan.widthPx;
        mask.m_heightPx = plan.heightPx;
        mask.m_rasterScale = plan.rasterScale;
        mask.m_dirty = false;
    }

    rcp<RenderImage> contentImage =
        host->contentCanvasImage(mask.m_contentCanvas.get());
    rcp<RenderImage> coverageImage =
        host->contentCanvasImage(mask.m_maskCanvas.get());
    if (contentImage == nullptr || coverageImage == nullptr)
    {
        return false;
    }

    // mask.m_box, not plan.box: on a frame that reused the cached rasters the
    // plan was re-fitted from scratch, and the pixels being composited belong
    // to whatever box they were rasterized for.
    auto placement = offscreen::beginComposite(renderer,
                                               host,
                                               plan,
                                               mask.m_rasterScale,
                                               mask.m_box);
    placement.renderer->drawImage(contentImage.get(),
                                  ImageSampler::LinearClamp(),
                                  BlendMode::srcOver,
                                  placement.opacity);
    offscreen::endComposite(placement);
    return true;
}
#else
bool Artboard::drawMasked(Renderer*, Drawable*, Drawable*) { return false; }
#endif

#ifdef RIVE_CANVAS
bool Artboard::drawCachedAsBitmap(Renderer* renderer)
{
    // Only reached when m_BitmapCache != nullptr (guarded in drawInternal).
    BitmapCache& cache = *m_BitmapCache;

    if (!cache.cacheEnabled())
    {
        // Authored off (or animated/bound off): behave as though the artboard
        // had no BitmapCache at all. The texture is released by
        // BitmapCache::cacheFlagsChanged when the bit clears.
        return false;
    }

    if (childOpacity() == 0.0f)
    {
        // Fully transparent: nothing to draw, and no need to (re)rasterize.
        // The pending change still has to be consumed the way drawContent()
        // would have on the vector path -- a host that gates frame submission
        // on didChange() (Unity does) otherwise resubmits this invisible
        // artboard every frame, forever. Fold it into the cache rather than
        // dropping it, so content that moved while it was transparent still
        // re-rasterizes when it becomes visible again instead of compositing
        // the raster it had before.
        cache.m_dirty = cache.m_dirty || didChange();
        m_didChange = false;
        return true;
    }

    Factory* f = factory();
    // canvasContentHost, not deferredCanvasHost: this only needs somewhere to
    // rasterize into, and an immediate renderer can provide that without
    // claiming its content is being recorded. The host also allocates the
    // canvas, so nothing here has to go looking for a device.
    auto* deferredHost = f ? f->canvasContentHost() : nullptr;
    // No host means nobody can give us an offscreen frame (a plain non-GPU or
    // test factory), so fall back to a normal vector draw.
    if (deferredHost == nullptr)
    {
        return false;
    }

    // The artboard's own box, which is not [0,0,width,height] in general: with
    // frameOrigin off, bounds() is offset by the origin -- and NestedArtboard
    // turns frameOrigin off on everything it hosts, which is the only way to
    // reach this path. Rasterizing [0,0,w,h] there would capture the wrong
    // region and composite it in the wrong place. bounds() also tracks the
    // resolved layout size rather than the authored width/height.
    const AABB box = bounds();
    const float w = box.width();
    const float h = box.height();
    if (w <= 0.0f || h <= 0.0f)
    {
        return false;
    }

    // drawContent applies the artboard's own rotation/scale, so a self
    // transform ends up baked into the raster -- while the target and the
    // composite below are both sized and placed from the untransformed box.
    // A scaled artboard would be cropped to its original extent, and a rotated
    // one flattened into an axis-aligned texture whose footprint no longer
    // matches what the vector path draws. Caching that correctly needs the
    // target sized from the transformed bounds and the composite placed by the
    // same transform; until then these artboards draw as vectors.
    if (hasSelfTransform())
    {
        return false;
    }

    // Chooses the raster size from the scale the artboard is actually viewed
    // at, and captures the CTM and modulated opacity the composite below needs.
    // See offscreen_raster.hpp for why each of those has to be read here,
    // while recording, rather than at replay.
    offscreen::RasterPlan plan;
    if (!offscreen::planRaster(renderer, box, cache.resolution(), &plan))
    {
        return false;
    }

    // Rebuild when there is no cache, it was explicitly invalidated (resolution
    // changed), the target size or raster scale changed (artboard resized, or
    // the artboard is being viewed at a different zoom), or the content changed
    // this frame.
    bool geomChanged = plan.widthPx != cache.m_widthPx ||
                       plan.heightPx != cache.m_heightPx ||
                       plan.rasterScale != cache.m_rasterScale;
    if (cache.m_canvas == nullptr || cache.m_dirty || geomChanged ||
        didChange())
    {
        renderIntoCanvas(deferredHost, plan);
    }
    if (cache.m_canvas == nullptr)
    {
        return false; // allocation failed; fall back to vector draw.
    }

    // Composite the cached texture in place of the vector content. The
    // renderer's CTM already includes the mount transform; drawImage() spans
    // (widthPx, heightPx), so undoing the raster's fit -- scale back to the
    // box, then move it to the box's corner -- maps a local point (lx,ly) to
    // CTM * (lx,ly), pixel-exact with the vector path.
    // The artboard's own opacity is already baked into the raster (host/render
    // opacity propagate to children and invalidate the cache via didChange()),
    // so the only opacity left to apply is an enclosing modulateOpacity()
    // scope -- and only on the fresh-renderer path, which does not inherit it.
    // Not necessarily the canvas's own image: some backends cannot sample
    // their canvas textures directly and stand in a companion for it.
    rcp<RenderImage> image =
        deferredHost->contentCanvasImage(cache.m_canvas.get());
    if (image == nullptr)
    {
        return false;
    }
    // Picks the renderer to composite through, saves, pixel snaps, and maps the
    // raster's pixel span back onto the box. m_rasterScale, not
    // plan.rasterScale: the raster being composited may have been built on an
    // earlier frame, and the mapping has to invert the scale it was actually
    // drawn at.
    auto placement = offscreen::beginComposite(renderer,
                                               deferredHost,
                                               plan,
                                               cache.m_rasterScale);
    placement.renderer->drawImage(image.get(),
                                  ImageSampler::LinearClamp(),
                                  BlendMode::srcOver,
                                  placement.opacity);
    offscreen::endComposite(placement);
    return true;
}

void Artboard::renderIntoCanvas(cmd::DeferredCanvasHost* deferredHost,
                                const offscreen::RasterPlan& plan)
{
    BitmapCache& cache = *m_BitmapCache;
    // Reuse the texture whenever it is already the right size. This runs on
    // every frame the artboard changes, and on an immediate host each of these
    // is a real GPU allocation -- re-minting one per frame both defeats the
    // point of a cache and thrashes the driver.
    if (cache.m_canvas == nullptr || cache.m_widthPx != plan.widthPx ||
        cache.m_heightPx != plan.heightPx)
    {
        // The host decides whether this needs real pixels now or can defer
        // them to whoever replays.
        cache.m_canvas =
            deferredHost->makeContentCanvas(plan.widthPx, plan.heightPx);
    }
    if (cache.m_canvas == nullptr)
    {
        return;
    }

    // The scope opens the content bracket and applies the raster transform;
    // drawContent (not drawInternal) so we never re-enter the cache hook.
    // clearColor is transparent black.
    bool opened = false;
    {
        offscreen::CanvasContentScope scope(deferredHost,
                                            cache.m_canvas.get(),
                                            plan,
                                            0);
        if (Renderer* r = scope.renderer())
        {
            opened = true;
            drawContent(r);
        }
    }
    if (!opened)
    {
        // The host could not open an offscreen frame (an unbacked canvas, or a
        // host that cannot nest one). Nothing was drawn, so the canvas holds
        // whatever it held before -- uninitialized on the first attempt. Drop
        // it rather than end a bracket that never began: the caller's null
        // check then takes the vector path, and leaving the cache dirty means
        // a later frame retries instead of compositing this hole forever.
        cache.m_canvas.reset();
        cache.m_widthPx = 0;
        cache.m_heightPx = 0;
        cache.m_dirty = true;
        return;
    }

    cache.m_widthPx = plan.widthPx;
    cache.m_heightPx = plan.heightPx;
    cache.m_rasterScale = plan.rasterScale;
    cache.m_dirty = false;
}
#endif

void Artboard::addToRenderPath(RenderPath* path, const Mat2D& transform)
{
    for (auto drawable = m_FirstDrawable; drawable != nullptr;
         drawable = drawable->prev)
    {
        if (drawable->isHidden() || !drawable->is<Shape>())
        {
            continue;
        }
        Shape* shape = drawable->as<Shape>();
        shape->addToRenderPath(path, transform);
    }
}

void Artboard::addToRawPath(RawPath& path, const Mat2D* transform)
{
    for (auto drawable = m_FirstDrawable; drawable != nullptr;
         drawable = drawable->prev)
    {
        if (drawable->isHidden() || !drawable->is<Shape>())
        {
            continue;
        }
        Shape* shape = drawable->as<Shape>();
        shape->addToRawPath(path, transform);
    }
}

Vec2D Artboard::origin() const
{
    return m_FrameOrigin
               ? Vec2D(0.0f, 0.0f)
               : Vec2D(-layoutWidth() * originX(), -layoutHeight() * originY());
}

void Artboard::xChanged()
{
    Super::xChanged();
    markHostTransformDirty();
}

void Artboard::yChanged()
{
    Super::yChanged();
    markHostTransformDirty();
}

// Origin has no dedicated animation/change plumbing, so a live change (e.g. a
// nested artboard origin override, or a keyframed artboard origin) would leave
// the cached render path and layout stale. Invalidate the background/clip path
// (updateRenderPath reads origin) and force the update pass to re-run so the
// content is repositioned. Components dirt is what a hosting NestedArtboard
// keys off (see NestedArtboard::advanceComponent) to re-run our updatePass;
// markHostTransformDirty notifies the host that our transform moved.
void Artboard::originXChanged()
{
    // Base originXChanged is a no-op; go straight to invalidation.
    addDirt(ComponentDirt::Path | ComponentDirt::Components);
    markHostTransformDirty();
}

void Artboard::originYChanged()
{
    addDirt(ComponentDirt::Path | ComponentDirt::Components);
    markHostTransformDirty();
}

AABB Artboard::bounds() const
{
    return m_FrameOrigin ? AABB(0.0f, 0.0f, layoutWidth(), layoutHeight())
                         : AABB::fromLTWH(-layoutWidth() * originX(),
                                          -layoutHeight() * originY(),
                                          layoutWidth(),
                                          layoutHeight());
}

AABB Artboard::worldBounds() const
{
    return AABB::fromLTWH(NodeBase::x(),
                          NodeBase::y(),
                          m_layout.width(),
                          m_layout.height());
}

bool Artboard::isTranslucent() const
{
    for (const auto sp : m_ShapePaints)
    {
        if (!sp->isTranslucent())
        {
            return false; // one opaque fill is sufficient to be opaque
        }
    }
    return true;
}

bool Artboard::hasAudio() const
{
    for (auto object : m_Objects)
    {
        if (object != nullptr && object->coreType() == AudioEventBase::typeKey)
        {
            return true;
        }
    }
    for (auto artboardHost : m_ArtboardHosts)
    {
        for (int i = 0; i < artboardHost->artboardCount(); i++)
        {
            auto artboard = artboardHost->artboardInstance(i);
            if (artboard != nullptr && artboard->hasAudio())
            {
                return true;
            }
        }
    }
    return false;
}

bool Artboard::isTranslucent(const LinearAnimation* anim) const
{
    // For now we're conservative/lazy -- if we see that any of our paints are
    // animated we assume that might make it non-opaque, so we early out
    for (const auto& obj : anim->m_KeyedObjects)
    {
        const auto ptr = this->resolve(obj->objectId());
        for (const auto sp : m_ShapePaints)
        {
            if (ptr == sp)
            {
                return true;
            }
        }
    }

    // If we get here, we have no animations, so just check our paints for
    // opacity
    return this->isTranslucent();
}

bool Artboard::isTranslucent(const LinearAnimationInstance* inst) const
{
    return this->isTranslucent(inst->animation());
}

std::string Artboard::animationNameAt(size_t index) const
{
    auto la = this->animation(index);
    return la ? la->name() : "";
}

// Helper: check if a FocusData has a parent FocusData within the artboard
// by walking up the component hierarchy
static bool hasParentFocusData(const FocusData* focusData)
{
    // FocusData's parent is a ContainerComponent (likely a Node)
    // Walk up to find if any ancestor Node has a FocusData child
    auto* current = focusData->parent();
    while (current != nullptr)
    {
        if (current->is<Node>())
        {
            auto* node = current->as<Node>();
            for (auto child : node->children())
            {
                if (child->is<FocusData>() && child != focusData)
                {
                    return true;
                }
            }
        }
        current = current->parent();
    }
    return false;
}

size_t Artboard::rootFocusDataCount() const
{
    size_t count = 0;
    for (auto* object : m_Objects)
    {
        if (object != nullptr && object->is<FocusData>())
        {
            if (!hasParentFocusData(object->as<FocusData>()))
            {
                count++;
            }
        }
    }
    return count;
}

FocusData* Artboard::rootFocusDataAt(size_t index) const
{
    size_t count = 0;
    for (auto* object : m_Objects)
    {
        if (object != nullptr && object->is<FocusData>())
        {
            if (!hasParentFocusData(object->as<FocusData>()))
            {
                if (count == index)
                {
                    return object->as<FocusData>();
                }
                count++;
            }
        }
    }
    return nullptr;
}

namespace
{
// Depth-first in scene (Container child) order so FocusManager child order
// (tab) matches the hierarchy, not the flat m_Objects / grouped passes.
// At most one FocusData is allowed as a direct child of a container; it is
// registered in a first pass, then child traversal skips that FocusData.
void buildFocusTreeVisit(FocusManager* focusManager,
                         Component* component,
                         rcp<FocusNode> focusNode)
{
    if (component == nullptr)
    {
        return;
    }
    if (component->is<NestedArtboard>())
    {
        auto* nestedHost = component->as<NestedArtboard>();
        // Wire the nested state machines to this manager before placing the
        // scope: setExternalFocusManager rebuilds the nested focus tree at the
        // manager root, so it must run first. Track whether any was actually
        // re-wired — a re-wire leaves the tree at the root and requires
        // re-homing under the scope (forceRebuild); an already-wired tree is
        // left in place.
        bool rewired = false;
        for (auto* animation : nestedHost->nestedAnimations())
        {
            if (animation->is<NestedStateMachine>())
            {
                auto* nsm = animation->as<NestedStateMachine>();
                auto* smi = nsm->stateMachineInstance();
                if (smi != nullptr && smi->focusManager() != focusManager)
                {
                    smi->setExternalFocusManager(focusManager);
                    rewired = true;
                }
            }
        }
        // Scope placement must be the final write so it overrides the root
        // rebuild above. For data-bound hosts this parents the nested focus
        // tree under the host's persistent structural scope; static hosts
        // build directly under focusNode. placeScope=true: the build pass is
        // the ordering authority — the scope is re-appended at the walk's
        // position.
        nestedHost->syncNestedFocusTree(focusNode,
                                        /*placeScope=*/true,
                                        /*forceRebuild=*/rewired);
    }
    else if (component->is<ArtboardComponentList>())
    {
        auto* list = component->as<ArtboardComponentList>();
        list->ensureListScopeFocusNode(focusManager, focusNode);
    }
    if (component->is<ContainerComponent>())
    {
        auto* cc = component->as<ContainerComponent>();
        FocusData* directFd = nullptr;
        for (Component* ch : cc->children())
        {
            if (ch != nullptr && ch->is<FocusData>())
            {
                directFd = ch->as<FocusData>();
                break;
            }
        }
        rcp<FocusNode> recurseWith;
        if (directFd != nullptr)
        {
            focusManager->addChild(focusNode, directFd->focusNode());
            recurseWith = directFd->focusNode();
        }
        else
        {
            recurseWith = focusNode;
        }
        for (Component* ch : cc->children())
        {
            if (ch == nullptr || ch->is<FocusData>())
            {
                continue;
            }
            buildFocusTreeVisit(focusManager, ch, recurseWith);
        }
    }
}
} // namespace

FocusManager* Artboard::ensureFocusManager()
{
    if (m_activeFocusManager != nullptr)
    {
        return m_activeFocusManager;
    }
    if (m_ownedFocusManager == nullptr)
    {
        m_ownedFocusManager = std::make_unique<FocusManager>();
    }
    m_activeFocusManager = m_ownedFocusManager.get();
    return m_activeFocusManager;
}

void Artboard::adoptFocusManager(FocusManager* manager)
{
    // A null manager means "stop borrowing", which falls back to our own if we
    // have one — the same shape as clearing the old external-manager override.
    if (manager == nullptr)
    {
        manager = m_ownedFocusManager.get();
    }
    if (m_activeFocusManager == manager)
    {
        return;
    }

    if (m_activeFocusManager != nullptr)
    {
        cleanupFocusTree();
    }

    m_activeFocusManager = manager;

    if (manager != nullptr)
    {
        buildFocusTree(manager, nullptr);
    }
}

void Artboard::buildFocusTree(FocusManager* focusManager,
                              rcp<FocusNode> parentFocusNode)
{
    if (focusManager == nullptr)
    {
        return;
    }

    // Store reference to the active focus manager
    setActiveFocusManager(focusManager);

#ifdef WITH_RIVE_TOOLS
    // Store the parent focus node if provided (for later retrieval by tools)
    if (parentFocusNode != nullptr)
    {
        m_externalParentFocusNode = parentFocusNode;
    }
    // Use explicit parent if provided, otherwise fall back to external parent
    rcp<FocusNode> effectiveParent = parentFocusNode != nullptr
                                         ? parentFocusNode
                                         : m_externalParentFocusNode;
#else
    rcp<FocusNode> effectiveParent = parentFocusNode;
#endif

    if (as<ContainerComponent>() != nullptr)
    {
        buildFocusTreeVisit(focusManager, this, std::move(effectiveParent));
    }
}

void Artboard::buildFocusTree(rcp<FocusNode> parentFocusNode)
{
    if (parentFocusNode == nullptr)
    {
        return;
    }
    auto* manager = parentFocusNode->manager();
    if (manager == nullptr)
    {
        return;
    }
    buildFocusTree(manager, parentFocusNode);
}

void Artboard::cleanupFocusTree()
{
    if (m_activeFocusManager == nullptr)
    {
        return;
    }

    // Remove all FocusData's FocusNodes from the FocusManager
    for (auto* obj : m_Objects)
    {
        if (obj != nullptr && obj->is<FocusData>())
        {
            auto* fd = obj->as<FocusData>();
            auto node = fd->focusNode();
            if (node == nullptr)
            {
                // FocusNode never lazily created — nothing to remove.
                continue;
            }
            // Remove the node when it belongs to this manager. Nodes owned by
            // a DIFFERENT live manager are left untouched.
            if (node->manager() == m_activeFocusManager)
            {
                m_activeFocusManager->removeChild(node);
            }
            else if (node->manager() == nullptr && node->parent() != nullptr)
            {
                // The node's manager was nulled while it is still attached —
                // either by an ancestor removal (removeChild clears m_manager
                // across a removed subtree) or by ~FocusManager, which nulls
                // m_manager tree-wide as it dies. Detach node-side only: in the
                // second case m_activeFocusManager is already dangling (it is
                // an unowned back-pointer, see setActiveFocusManager) and
                // touching it is a use-after-free. Nothing is lost by skipping
                // markFocusableContentDirty here — if the manager is alive, the
                // ancestor removal that nulled m_manager already marked it.
                node->removeFromParent();
            }
        }
    }

    // Propagate cleanup to nested artboards that share our FocusManager
    for (auto* nestedArtboardHost : m_NestedArtboards)
    {
        auto* nestedArtboard = nestedArtboardHost->artboardInstance(0);
        if (nestedArtboard != nullptr &&
            nestedArtboard->focusManager() == m_activeFocusManager)
        {
            nestedArtboard->cleanupFocusTree();
        }
    }

    // Propagate cleanup to ArtboardComponentList items
    for (auto* componentList : m_ComponentLists)
    {
        for (size_t i = 0; i < componentList->artboardCount(); i++)
        {
            auto* nestedArtboard =
                componentList->artboardInstance(static_cast<int>(i));
            if (nestedArtboard != nullptr &&
                nestedArtboard->focusManager() == m_activeFocusManager)
            {
                nestedArtboard->cleanupFocusTree();
            }
        }
    }

    for (auto* componentList : m_ComponentLists)
    {
        componentList->removeListScopeFocusNode();
    }

    // Fall back to our own manager rather than to "no manager"
    m_activeFocusManager = m_ownedFocusManager.get();
}

#ifdef WITH_RIVE_TOOLS
void Artboard::setExternalParentFocusNode(rcp<FocusNode> node)
{
    m_externalParentFocusNode = std::move(node);
}

rcp<FocusNode> Artboard::externalParentFocusNode() const
{
    return m_externalParentFocusNode;
}

void Artboard::collapseSingle(bool value) { Component::collapse(value); }
#endif

// Builds the semantic tree for this artboard. Iterates all objects,
// registers each SemanticData's SemanticNode with the manager, then
// propagates to nested artboards using findClosestSemanticNode() for
// parent resolution across artboard boundaries.
//
// For nested artboards (those with a host), a boundary SemanticNode is
// created and inserted as the parent of all semantic nodes within this
// artboard. Boundary nodes are structural-only — skipped during
// flattening — but enable better subtree collapse/uncollapse and
// targeted bounds dirtying when the host transform changes.
void Artboard::buildSemanticTree(SemanticManager* semanticManager,
                                 rcp<SemanticNode> parentSemanticNode)
{
    if (semanticManager == nullptr)
    {
        return;
    }

    // Store reference to the active semantic manager
    setActiveSemanticManager(semanticManager);

    // For nested artboards, create a boundary node that acts as the
    // structural root of this artboard's semantic subtree.
    rcp<SemanticNode> effectiveParent = parentSemanticNode;
    if (host() != nullptr)
    {
        if (m_semanticBoundaryNode == nullptr)
        {
            // Id is assigned by the SemanticManager on addChild() below.
            m_semanticBoundaryNode = rcp<SemanticNode>(new SemanticNode());
            m_semanticBoundaryNode->isBoundaryNode(true);
            m_semanticBoundaryNode->boundaryArtboard(this);
        }
        semanticManager->addChild(parentSemanticNode, m_semanticBoundaryNode);
        // Seed the boundary as dirty so the first drainDiff() resolves its
        // bounds from the artboard rect even when semantics are enabled on
        // an already-settled scene (no subsequent WorldTransform dirt to
        // trigger this via the normal update cycle).
        markSemanticBoundaryTransformDirty();
        effectiveParent = m_semanticBoundaryNode;
    }

    // Register all SemanticData in this artboard
    for (auto* obj : m_Objects)
    {
        if (obj != nullptr && obj->is<SemanticData>())
        {
            auto* sd = obj->as<SemanticData>();
            auto* localParent = sd->findParentSemanticData();

            rcp<SemanticNode> parentNode = localParent != nullptr
                                               ? localParent->semanticNode()
                                               : effectiveParent;

            semanticManager->addChild(parentNode, sd->semanticNode());
            sd->syncSemanticTreeVisibility();
        }
    }

    // Propagate semantic registration to nested artboards that might have been
    // created before this artboard's semanticManager was available.
    //
    // We check if the nested artboard's semanticManager is DIFFERENT from ours.
    // If it is, that means it created its own internal semanticManager when it
    // should be sharing the parent's. We rebuild its semantic tree with the
    // correct shared semanticManager.

    // Handle NestedArtboard instances
    for (auto* nestedArtboardHost : m_NestedArtboards)
    {
        // Find closest semantic node (handles artboard boundaries)
        auto hostParentNode =
            SemanticData::findClosestSemanticNode(nestedArtboardHost);
        if (hostParentNode == nullptr)
        {
            hostParentNode = effectiveParent;
        }

        auto* nestedArtboard = nestedArtboardHost->artboardInstance(0);
        if (nestedArtboard != nullptr &&
            nestedArtboard->semanticManager() != semanticManager)
        {
            // Clean up old semantic tree if it exists (with wrong
            // semanticManager)
            nestedArtboard->cleanupSemanticTree();
            nestedArtboard->buildSemanticTree(semanticManager, hostParentNode);
        }
    }

    // Handle ArtboardComponentList instances
    for (auto* componentList : m_ComponentLists)
    {
        // Find closest semantic node (handles artboard boundaries)
        auto hostParentNode =
            SemanticData::findClosestSemanticNode(componentList);
        if (hostParentNode == nullptr)
        {
            hostParentNode = effectiveParent;
        }

        for (size_t i = 0; i < componentList->artboardCount(); i++)
        {
            auto* nestedArtboard =
                componentList->artboardInstance(static_cast<int>(i));
            if (nestedArtboard != nullptr &&
                nestedArtboard->semanticManager() != semanticManager)
            {
                // Clean up old semantic tree if it exists (with wrong
                // semanticManager)
                nestedArtboard->cleanupSemanticTree();
                nestedArtboard->buildSemanticTree(semanticManager,
                                                  hostParentNode);
            }
        }
    }
}

void Artboard::cleanupSemanticTree()
{
    if (m_activeSemanticManager == nullptr)
    {
        return;
    }

    // Propagate cleanup to nested artboards that share our SemanticManager.
    // Done FIRST so their boundary nodes are removed before we remove ours.
    for (auto* nestedArtboardHost : m_NestedArtboards)
    {
        auto* nestedArtboard = nestedArtboardHost->artboardInstance(0);
        if (nestedArtboard != nullptr &&
            nestedArtboard->semanticManager() == m_activeSemanticManager)
        {
            nestedArtboard->cleanupSemanticTree();
        }
    }

    // Propagate cleanup to ArtboardComponentList items
    for (auto* componentList : m_ComponentLists)
    {
        for (size_t i = 0; i < componentList->artboardCount(); i++)
        {
            auto* nestedArtboard =
                componentList->artboardInstance(static_cast<int>(i));
            if (nestedArtboard != nullptr &&
                nestedArtboard->semanticManager() == m_activeSemanticManager)
            {
                nestedArtboard->cleanupSemanticTree();
            }
        }
    }

    // Remove all SemanticData's SemanticNodes from the SemanticManager.
    // Use hasSemanticNode() to avoid lazy-creating a node during cleanup.
    for (auto* obj : m_Objects)
    {
        if (obj != nullptr && obj->is<SemanticData>())
        {
            auto* sd = obj->as<SemanticData>();
            if (!sd->hasSemanticNode())
            {
                continue;
            }
            auto node = sd->semanticNode();
            if (node != nullptr && node->manager() == m_activeSemanticManager)
            {
                m_activeSemanticManager->removeChild(node);
            }
        }
    }

    // Remove the boundary node for this artboard (if any).
    if (m_semanticBoundaryNode != nullptr &&
        m_semanticBoundaryNode->manager() == m_activeSemanticManager)
    {
        m_activeSemanticManager->removeChild(m_semanticBoundaryNode);
    }
    m_semanticBoundaryNode = nullptr;

    // Clear the active semantic manager reference
    m_activeSemanticManager = nullptr;
}

// Walk the semantic subtree under a boundary node and collapse each
// SemanticData directly via the back-pointer. O(K) where K = semantic
// nodes under this boundary.
static void collapseBoundarySubtree(SemanticNode* node, bool value)
{
    // Copy children before iterating — collapse(true) calls
    // removeChild which mutates the original vector.
    std::vector<rcp<SemanticNode>> children(node->children());
    for (const auto& child : children)
    {
        auto* sd = child->semanticData();
        if (sd != nullptr && sd->isCollapsed() != value)
        {
            sd->collapse(value);
        }
        collapseBoundarySubtree(child.get(), value);
    }
}

// Semantic-only collapse for this artboard's semantic nodes.
// When collapsing, walks the boundary's semantic subtree (O(K) semantic
// nodes). When uncollapsing, falls back to m_Objects because
// SemanticData::collapse(false) re-parents nodes outside the boundary.
void Artboard::collapseSemanticBoundary(bool value)
{
    if (m_activeSemanticManager == nullptr)
    {
        return;
    }
    if (value && m_semanticBoundaryNode != nullptr)
    {
        // Fast path: walk the boundary tree.
        collapseBoundarySubtree(m_semanticBoundaryNode.get(), true);
    }
    else
    {
        // Uncollapse or no boundary: scan artboard objects.
        for (auto* obj : m_Objects)
        {
            if (obj != nullptr && obj->is<SemanticData>())
            {
                auto* sd = obj->as<SemanticData>();
                if (sd->isCollapsed() != value)
                {
                    sd->collapse(value);
                }
            }
        }
    }

    if (!value)
    {
        markSemanticBoundaryTransformDirty();
    }
}

// Recursively mark all semantic nodes under the boundary as bounds-dirty.
// Called when the host transform changes so bounds are recalculated in
// root artboard space.
void Artboard::markSemanticBoundaryTransformDirty()
{
    if (m_semanticBoundaryNode == nullptr || m_activeSemanticManager == nullptr)
    {
        return;
    }
    m_activeSemanticManager->markBoundaryDirty(m_semanticBoundaryNode->id());
}

std::string Artboard::stateMachineNameAt(size_t index) const
{
    auto sm = this->stateMachine(index);
    return sm ? sm->name() : "";
}

LinearAnimation* Artboard::animation(const std::string& name) const
{
    for (auto animation : m_Animations)
    {
        if (animation->name() == name)
        {
            return animation;
        }
    }
    return nullptr;
}

LinearAnimation* Artboard::animation(size_t index) const
{
    if (index >= m_Animations.size())
    {
        return nullptr;
    }
    return m_Animations[index];
}

StateMachine* Artboard::stateMachine(const std::string& name) const
{
    for (auto machine : m_StateMachines)
    {
        if (machine->name() == name)
        {
            return machine;
        }
    }
    return nullptr;
}

StateMachine* Artboard::stateMachine(size_t index) const
{
    if (index >= m_StateMachines.size())
    {
        return nullptr;
    }
    return m_StateMachines[index];
}

int Artboard::defaultStateMachineIndex() const
{
    int index = defaultStateMachineId();
    if ((size_t)index >= m_StateMachines.size())
    {
        index = -1;
    }
    return index;
}

NestedArtboard* Artboard::nestedArtboard(const std::string& name) const
{
    for (auto nested : m_NestedArtboards)
    {
        if (nested->name() == name)
        {
            return nested;
        }
    }
    return nullptr;
}

NestedArtboard* Artboard::nestedArtboardAtPath(const std::string& path) const
{
    // name parameter can be a name or a path to recursively find a nested
    // artboard
    std::string delimiter = "/";
    size_t firstDelim = path.find(delimiter);
    std::string artboardName =
        firstDelim == std::string::npos ? path : path.substr(0, firstDelim);
    std::string restOfPath = firstDelim == std::string::npos
                                 ? ""
                                 : path.substr(firstDelim + 1, path.size());

    // Find the nested artboard at this level
    if (!artboardName.empty())
    {
        auto nested = nestedArtboard(artboardName);
        if (nested != nullptr)
        {
            if (restOfPath.empty())
            {
                return nested;
            }
            else
            {
                auto artboard = nested->artboardInstance();
                return artboard->nestedArtboardAtPath(restOfPath);
            }
        }
    }
    return nullptr;
}

// std::unique_ptr<ArtboardInstance> Artboard::instance() const
// {
//     std::unique_ptr<ArtboardInstance> artboardClone(new ArtboardInstance);
//     artboardClone->copy(*this);

//     artboardClone->m_Factory = m_Factory;
//     artboardClone->m_FrameOrigin = m_FrameOrigin;
//     artboardClone->m_IsInstance = true;

//     std::vector<Core*>& cloneObjects = artboardClone->m_Objects;
//     cloneObjects.push_back(artboardClone.get());

//     if (!m_Objects.empty())
//     {
//         // Skip first object (artboard).
//         auto itr = m_Objects.begin();
//         while (++itr != m_Objects.end())
//         {
//             auto object = *itr;
//             cloneObjects.push_back(object == nullptr ? nullptr :
//             object->clone());
//         }
//     }

//     for (auto animation : m_Animations)
//     {
//         artboardClone->m_Animations.push_back(animation);
//     }
//     for (auto stateMachine : m_StateMachines)
//     {
//         artboardClone->m_StateMachines.push_back(stateMachine);
//     }

//     if (artboardClone->initialize() != StatusCode::Ok)
//     {
//         artboardClone = nullptr;
//     }

//     assert(artboardClone->isInstance());
//     return artboardClone;
// }

void Artboard::frameOrigin(bool value)
{
    if (value == m_FrameOrigin)
    {
        return;
    }
    m_FrameOrigin = value;
    addDirt(ComponentDirt::Path);
}

StatusCode Artboard::import(ImportStack& importStack)
{
    auto backboardImporter =
        importStack.latest<BackboardImporter>(Backboard::typeKey);
    if (backboardImporter == nullptr)
    {
        return StatusCode::MissingObject;
    }

    StatusCode result = Super::import(importStack);
    if (result == StatusCode::Ok)
    {
        backboardImporter->addArtboard(this);
    }
    else
    {
        backboardImporter->addMissingArtboard();
    }
    return result;
}

void Artboard::buildDataContext(rcp<DataContext> value) {}

void Artboard::internalDataContext(rcp<DataContext> value)
{
    // Set the context before recursing into the artboard hosts; they read it
    // back off this artboard while they bind. The binds are walked after.
    dataBindContext(value);
    syncInstanceValueBinds();
    for (auto artboardHost : m_ArtboardHosts)
    {
        auto hostValue =
            value->getViewModelInstance(artboardHost->dataBindPath());
        if (hostValue != nullptr && hostValue->is<ViewModelInstance>())
        {
            artboardHost->bindViewModelInstance(hostValue, value);
        }
        else
        {
            artboardHost->internalDataContext(value);
        }
    }
    bindDataBindsFromContext();
    sortDataBinds();
    for (auto* scriptedObject : m_ScriptedObjects)
    {
        scriptedObject->dataContext(value);
    }
    initScriptedObjects();
}

void Artboard::rebind() { internalDataContext(dataBindContext()); }

void Artboard::relinkDataContext()
{
    wakeIfQuietRow();
    if (dataBindContext() == nullptr)
    {
        return;
    }
    for (auto artboardHost : m_ArtboardHosts)
    {
        rcp<ViewModelInstance> value = dataBindContext()->getViewModelInstance(
            artboardHost->dataBindPath());
        if (value == nullptr)
        {
            value = dataBindContext()->mainViewModelInstance();
        }
        artboardHost->relinkDataContext(value);
    }
}

void Artboard::rebuildDataBind(DataBind* dataBind)
{
    if (dataBind->is<DataBindContext>())
    {
        dataBind->as<DataBindContext>()->bindFromContext(
            dataBindContext().get());
    }
};

void Artboard::unbind()
{
    clearDataContext();
    unbindDataBinds();
    for (auto artboardHost : m_ArtboardHosts)
    {
        artboardHost->unbind();
    }
}

void Artboard::clearDataContext()
{
    if (dataBindContext() != nullptr)
    {
        dataBindContext()->removeDependentContainer(this);
        dataBindContext(nullptr);
        syncInstanceValueBinds();
    }
    for (auto artboardHost : m_ArtboardHosts)
    {
        artboardHost->clearDataContext();
    }
    for (auto* scriptedObject : m_ScriptedObjects)
    {
        scriptedObject->resetLuaInit();
    }
}

float Artboard::volume() const { return m_volume; }
void Artboard::volume(float value)
{
    m_volume = value;
    for (auto artboardHost : m_ArtboardHosts)
    {
        for (int i = 0; i < artboardHost->artboardCount(); i++)
        {
            auto artboard = artboardHost->artboardInstance(i);
            if (artboard != nullptr)
            {
                artboard->volume(value);
            }
        }
    }
}

void Artboard::hostOpacity(float value)
{
    if (m_hostOpacity == value)
    {
        return;
    }
    m_hostOpacity = value;
    // Re-propagate opacity to our contents. The property itself is untouched,
    // so we dirty render opacity directly rather than through opacity(...).
    addDirt(ComponentDirt::RenderOpacity, true);
}

void Artboard::dataContext(rcp<DataContext> value)
{
    internalDataContext(value);
}

rcp<const File> Artboard::artboardFile() const { return nullptr; }

void Artboard::bindViewModelInstance(rcp<ViewModelInstance> viewModelInstance)
{
    bindViewModelInstance(viewModelInstance, nullptr);
}

void Artboard::bindViewModelInstance(rcp<ViewModelInstance> viewModelInstance,
                                     rcp<DataContext> parent)
{
    if (viewModelInstance == nullptr)
    {
        unbind();
        return;
    }
    setViewModelInstance(std::move(viewModelInstance));
    if (parent != nullptr && dataBindContext() != nullptr)
    {
        dataBindContext()->parent(parent);
    }
    bind();
}

void Artboard::setViewModelInstance(rcp<ViewModelInstance> viewModelInstance)
{
    if (viewModelInstance == nullptr)
    {
        return;
    }
    if (dataBindContext() == nullptr)
    {
        dataBindContext(make_rcp<DataContext>(viewModelInstance));
        dataBindContext()->addDependentContainer(this);
        return;
    }
    // The data context re-points every attached container (this artboard and
    // any state machines sharing the context) off the old main and onto the new
    // one.
    dataBindContext()->setMainViewModelInstance(viewModelInstance);
}

void Artboard::bindViewModelInstances(
    std::vector<rcp<ViewModelInstance>> viewModelInstances,
    rcp<DataContext> parent)
{
    if (viewModelInstances.empty())
    {
        unbind();
        return;
    }
    clearDataContext();
    auto dataContext = make_rcp<DataContext>(std::move(viewModelInstances));
    dataContext->addDependentContainer(this);
    dataContext->parent(parent);
    internalDataContext(dataContext);
}

void Artboard::bind()
{
    if (dataBindContext() != nullptr)
    {
        internalDataContext(dataBindContext());
    }
}

rcp<ViewModelInstance> Artboard::globalViewModelInstance(
    const std::string& name)
{
    // Pure read: returns the instance in the named slot only if one has been
    // set/bound; never creates.
    if (dataBindContext() == nullptr)
    {
        return nullptr;
    }
    auto f = artboardFile();
    if (f == nullptr)
    {
        return nullptr;
    }
    return dataBindContext()->instanceForSlot(f->viewModelId(name));
}

bool Artboard::setGlobalViewModelInstance(
    const std::string& name,
    rcp<ViewModelInstance> viewModelInstance)
{
    // A null instance is allowed: it empties the named slot below.
    auto f = artboardFile();
    if (f == nullptr)
    {
        return false;
    }
    // The slot is addressed by the named view model (its file index), not by
    // the instance's own view model — so an override instance of a different
    // view model can be placed on the slot.
    uint32_t slotKey = f->viewModelId(name);
    if (slotKey >= f->viewModelCount())
    {
        return false;
    }
    // Only global view models get a slot; a non-global name is not a valid
    // global slot and must not be slotted.
    auto slotViewModel = f->viewModel(slotKey);
    if (slotViewModel == nullptr ||
        static_cast<ViewModelType>(slotViewModel->viewModelType()) !=
            ViewModelType::global)
    {
        return false;
    }
    if (dataBindContext() == nullptr)
    {
        // Nothing to clear when there is no context yet; only create one when
        // actually placing an instance.
        if (viewModelInstance == nullptr)
        {
            return true;
        }
        dataBindContext(make_rcp<DataContext>(rcp<ViewModelInstance>(nullptr)));
        dataBindContext()->addDependentContainer(this);
    }
    // The data context re-points every attached container off any previous
    // instance occupying this slot and onto the new one (or empties the slot
    // when the instance is null).
    dataBindContext()->setViewModelInstanceForSlot(slotKey, viewModelInstance);
    return true;
}

bool Artboard::isAncestor(const Artboard* artboard)
{
    if (artboard != nullptr && m_artboardSource == artboard->artboardSource())
    {
        return true;
    }
    if (parentArtboard() != nullptr)
    {
        return parentArtboard()->isAncestor(artboard);
    }
#ifdef WITH_RIVE_TOOLS
    // Editor artboards don't have a host, so we expose a function that calls
    // the host in dart.
    if (m_isAncestorCallback != nullptr)
    {
        // Dart can't return booleans to cpp, so we use a uint_8 instead
        auto isAncestor =
            m_isAncestorCallback(callbackUserData, artboard->artboardId());
        if (isAncestor == 1)
        {
            return true;
        }
    }
#endif
    return false;
}

void Artboard::changed()
{
    if (!m_didChange)
    {
        m_didChange = true;
        if (parentArtboard())
        {
            parentArtboard()->changed();
        }
    }
}

////////// ArtboardInstance

#include "rive/animation/linear_animation_instance.hpp"
#include "rive/animation/state_machine_instance.hpp"

ArtboardInstance::ArtboardInstance() {}

ArtboardInstance::~ArtboardInstance() {}

void ArtboardInstance::file(rcp<const File> file) { m_file = std::move(file); }

rcp<const File> ArtboardInstance::file() const { return m_file; }

rcp<const File> ArtboardInstance::artboardFile() const { return m_file; }

std::unique_ptr<LinearAnimationInstance> ArtboardInstance::animationAt(
    size_t index)
{
    auto la = this->animation(index);
    return la ? std::make_unique<LinearAnimationInstance>(la, this) : nullptr;
}

std::unique_ptr<LinearAnimationInstance> ArtboardInstance::animationNamed(
    const std::string& name)
{
    auto la = this->animation(name);
    return la ? std::make_unique<LinearAnimationInstance>(la, this) : nullptr;
}

std::unique_ptr<StateMachineInstance> ArtboardInstance::stateMachineAt(
    size_t index)
{
    auto sm = this->stateMachine(index);
    if (sm == nullptr)
    {
        return nullptr;
    }
    auto smInstance = std::make_unique<StateMachineInstance>(sm, this);
    if (auto dc = dataContext())
    {
        smInstance->inheritDataContext(dc);
    }
    return smInstance;
}

std::unique_ptr<StateMachineInstance> ArtboardInstance::stateMachineNamed(
    const std::string& name)
{
    auto sm = this->stateMachine(name);
    if (sm == nullptr)
    {
        return nullptr;
    }
    auto smInstance = std::make_unique<StateMachineInstance>(sm, this);
    if (auto dc = dataContext())
    {
        smInstance->inheritDataContext(dc);
    }
    return smInstance;
}

std::unique_ptr<StateMachineInstance> ArtboardInstance::defaultStateMachine()
{
    const int index = this->defaultStateMachineIndex();
    return index >= 0 ? this->stateMachineAt(index) : nullptr;
}

std::unique_ptr<Scene> ArtboardInstance::defaultScene()
{
    std::unique_ptr<Scene> scene = this->defaultStateMachine();
    if (!scene)
    {
        scene = this->stateMachineAt(0);
    }
    if (!scene)
    {
        scene = this->animationAt(0);
    }
    return scene;
}

SMIInput* ArtboardInstance::input(const std::string& name,
                                  const std::string& path)
{
    return getNamedInput<SMIInput>(name, path);
}

template <typename InstType>
InstType* ArtboardInstance::getNamedInput(const std::string& name,
                                          const std::string& path)
{
    if (!path.empty())
    {
        auto nestedArtboard = nestedArtboardAtPath(path);
        if (nestedArtboard != nullptr)
        {
            auto input = nestedArtboard->input(name);
            if (input != nullptr && input->input() != nullptr)
            {
                return static_cast<InstType*>(input->input());
            }
        }
    }
    return nullptr;
}

SMIBool* ArtboardInstance::getBool(const std::string& name,
                                   const std::string& path)
{
    return getNamedInput<SMIBool>(name, path);
}

SMINumber* ArtboardInstance::getNumber(const std::string& name,
                                       const std::string& path)
{
    return getNamedInput<SMINumber>(name, path);
}
SMITrigger* ArtboardInstance::getTrigger(const std::string& name,
                                         const std::string& path)
{
    return getNamedInput<SMITrigger>(name, path);
}

TextValueRun* ArtboardInstance::getTextRun(const std::string& name,
                                           const std::string& path)
{
    if (path.empty())
    {
        return nullptr;
    }

    auto nestedArtboard = nestedArtboardAtPath(path);
    if (nestedArtboard == nullptr)
    {
        return nullptr;
    }

    auto artboardInstance = nestedArtboard->artboardInstance();
    if (artboardInstance == nullptr)
    {
        return nullptr;
    }

    return artboardInstance->find<TextValueRun>(name);
}

#ifdef EXTERNAL_RIVE_AUDIO_ENGINE
rcp<AudioEngine> Artboard::audioEngine() const { return m_audioEngine; }
void Artboard::audioEngine(rcp<AudioEngine> audioEngine)
{
    m_audioEngine = audioEngine;
    for (auto artboardHost : m_ArtboardHosts)
    {
        for (int i = 0; i < artboardHost->artboardCount(); i++)
        {
            auto artboard = artboardHost->artboardInstance(i);
            if (artboard != nullptr)
            {
                artboard->audioEngine(audioEngine);
            }
        }
    }
}
#endif
