#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;
#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.
    auto gatherVmObjects = [&](Core* object) {
        if (object == nullptr || object == this)
        {
            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)
    {
        gatherVmObjects(object);
    }
    for (auto object : m_invalidObjects)
    {
        gatherVmObjects(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)
{
    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)
{
    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() { syncInstanceValueBinds(); }

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)
{
    // 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)
{
    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()
{
#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()
{
    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
