#include "rive/animation/keyframe_interpolator.hpp"
#include "rive/artboard.hpp"
#include "rive/artboard_component_list.hpp"
#include "rive/constraints/layout_constraint.hpp"
#include "rive/drawable.hpp"
#include "rive/factory.hpp"
#include "rive/importers/import_stack.hpp"
#include "rive/intrinsically_sizeable.hpp"
#include "rive/layout_component.hpp"
#include "rive/component_origin.hpp"
#include "rive/layout/grid_track.hpp"
#include "rive/layout/layout_style_applier.hpp"
#include "rive/nested_artboard_layout.hpp"
#include "rive/node.hpp"
#include "rive/math/aabb.hpp"
#include "rive/shapes/path.hpp"
#include "rive/shapes/paint/fill.hpp"
#include "rive/shapes/paint/shape_paint.hpp"
#include "rive/shapes/paint/stroke.hpp"
#include "rive/solo.hpp"
#include "rive/layout/layout_data.hpp"
#include "rive/layout/layout_component_style.hpp"
#ifdef WITH_RIVE_LAYOUT
#include "rive/transform_component.hpp"
#include "yoga/YGEnums.h"
#include "yoga/YGFloatOptional.h"
#endif
#include <vector>

using namespace rive;

#ifdef WITH_RIVE_LAYOUT
void LayoutComponent::addLayoutStyleApplier(LayoutStyleApplier* applier)
{
    if (m_layoutData != nullptr)
    {
        m_layoutData->addApplier(applier);
    }
}
#endif

bool rive::isTransparentLayoutContainer(Component* component)
{
    return component->coreType() == NodeBase::typeKey || component->is<Solo>();
}

bool rive::joinsLayoutThroughContainer(Component* component)
{
    if (!component->is<ArtboardComponentList>())
    {
        return true;
    }
    auto flags =
        static_cast<DrawableFlag>(component->as<Drawable>()->drawableFlags());
    return (flags & DrawableFlag::ParticipatesInLayout) ==
           DrawableFlag::ParticipatesInLayout;
}

namespace
{
// Whether content-sizing stops here. Narrower than
// isTransparentLayoutContainer: a plain group is a barrier (its contents are
// free content), but a Solo is not — its children content-size just as direct
// children of the layout do.
bool stopsContentSizing(Component* component)
{
    return component->coreType() == NodeBase::typeKey;
}

// Visit every provider that belongs to a layout — its direct children, plus any
// nested inside transparent containers; depth-first, so layout order follows
// hierarchy order. Nested LayoutComponents and providers are leaves here (they
// own their subtree). Every child-walking layout pass goes through this, so a
// nested participant is collected, sized, cascaded and re-synced like a direct
// child.
template <typename F>
void forEachLayoutProvider(Component* from, F&& visit, bool nested = false)
{
    // A Solo only lets its active child through.
    if (from->is<Solo>())
    {
        if (auto* active = from->as<Solo>()->activeComponent())
        {
            if (auto* provider = LayoutNodeProvider::from(active))
            {
                if (!nested || joinsLayoutThroughContainer(active))
                {
                    visit(active, provider);
                }
            }
            else if (isTransparentLayoutContainer(active))
            {
                forEachLayoutProvider(active, visit, true);
            }
        }
        return;
    }
    for (auto* child : from->as<ContainerComponent>()->children())
    {
        if (auto* provider = LayoutNodeProvider::from(child))
        {
            if (!nested || joinsLayoutThroughContainer(child))
            {
                visit(child, provider);
            }
        }
        else if (isTransparentLayoutContainer(child))
        {
            forEachLayoutProvider(child, visit, true);
        }
    }
}

// Only reached when the HasComponentOrigin flag says one exists, so the common
// case never walks.
ComponentOrigin* originChild(const ContainerComponent* owner)
{
    for (auto* child : owner->children())
    {
        if (child->is<ComponentOrigin>())
        {
            return child->as<ComponentOrigin>();
        }
    }
    return nullptr;
}
} // namespace

LayoutComponent* rive::contentSizingLayout(Component* parent)
{
    for (Component* p = parent; p != nullptr; p = p->parent())
    {
        if (p->is<LayoutComponent>())
        {
            return p->as<LayoutComponent>();
        }
        // A group stops content sizing; a provider is sized by the engine.
        if (stopsContentSizing(p) || LayoutNodeProvider::from(p) != nullptr)
        {
            return nullptr;
        }
        auto* sizeable = IntrinsicallySizeable::from(p);
        if (sizeable != nullptr && !sizeable->shouldPropagateSizeToChildren())
        {
            return nullptr;
        }
    }
    return nullptr;
}

LayoutComponent* rive::owningLayout(Component* component)
{
    for (Component* p = component; p != nullptr; p = p->parent())
    {
        if (p->is<LayoutComponent>())
        {
            return p->as<LayoutComponent>();
        }
    }
    return nullptr;
}

#if defined(WITH_RIVE_LAYOUT) && defined(WITH_RIVE_TOOLS) && defined(DEBUG)
uint32_t LayoutData::count = 0;
#endif

float LayoutComponent::pivotOriginX() const
{
    if (!hasLayoutFlag(LayoutComponentFlags::HasComponentOrigin))
    {
        return 0.0f;
    }
    auto* origin = originChild(this);
    return origin != nullptr ? origin->originX() : 0.0f;
}

float LayoutComponent::pivotOriginY() const
{
    if (!hasLayoutFlag(LayoutComponentFlags::HasComponentOrigin))
    {
        return 0.0f;
    }
    auto* origin = originChild(this);
    return origin != nullptr ? origin->originY() : 0.0f;
}

void LayoutComponent::buildDependencies()
{
    Super::buildDependencies();
    if (parent() != nullptr)
    {
        parent()->addDependent(this);
    }
    // Set the blend mode on all the shape paints. If we ever animate this
    // property, we'll need to update it in the update cycle/mark dirty when the
    // blend mode changes.
    for (auto paint : m_ShapePaints)
    {
        paint->blendMode(blendMode());
    }
}

Core* LayoutComponent::hitTest(HitInfo*, const Mat2D&) { return nullptr; }

bool LayoutComponent::hitTestPoint(const Vec2D& position,
                                   bool skipOnUnclipped,
                                   bool isPrimaryHit)
{
    Mat2D inverseWorld;
    if (worldTransform().invert(&inverseWorld))
    {
        // If the layout is not clipped and skipOnUnclipped is true, we
        // don't care about whether it contains the position
        auto canSkip = skipOnUnclipped && !this->clip();
        if (!canSkip)
        {
            auto localWorld = inverseWorld * position;
            if (this->is<Artboard>())
            {
                auto artboard = this->as<Artboard>();
                if (artboard->originX() != 0 || artboard->originY() != 0)
                {
                    localWorld +=
                        Vec2D(artboard->originX() * artboard->layoutWidth(),
                              artboard->originY() * artboard->layoutHeight());
                }
            }
            if (!localBounds().contains(localWorld))
            {
                return false;
            }
        }
        return Drawable::hitTestPoint(position, true, isPrimaryHit);
    }
    return false;
}

StatusCode LayoutComponent::import(ImportStack& importStack)
{
    // Files exported before 7.3 composed a layout's transform from the solved
    // slot alone, so any stored rotation/scale was written but never applied.
    // Keep that legacy behavior for those files; newer files compose it on top
    // of the slot. See File::minorVersion.
    int major = importStack.majorVersion();
    int minor = importStack.minorVersion();
    setLayoutFlag(LayoutComponentFlags::ComposeTransform,
                  major > 7 || (major == 7 && minor >= 3));
    return Super::import(importStack);
}

Core* LayoutComponent::clone() const
{
    LayoutComponent* twin = LayoutComponentBase::clone()->as<LayoutComponent>();
    twin->setLayoutFlag(LayoutComponentFlags::ComposeTransform,
                        hasLayoutFlag(LayoutComponentFlags::ComposeTransform));
    // The clip-may-be-dynamic (KeyedObject::onAddedDirty) and listener-target
    // (StateMachineListener::onAddedClean) reasons for ForceDrawableProxy are
    // stamped only on the source, since instances share animations and state
    // machines. Carry the flag so an instance's proxy is still injected before
    // its first sort. (The scroll-interaction reason re-marks per instance in
    // buildDependencies, so carrying it here is a harmless no-op for that
    // case.)
    twin->setLayoutFlag(
        LayoutComponentFlags::ForceDrawableProxy,
        hasLayoutFlag(LayoutComponentFlags::ForceDrawableProxy));
    return twin;
}

bool LayoutComponent::composesLayoutOffset() const
{
    return hasLayoutFlag(LayoutComponentFlags::ComposeTransform) &&
           !is<Artboard>();
}

Vec2D LayoutComponent::localAnchor() const
{
    if (!hasLayoutFlag(LayoutComponentFlags::HasComponentOrigin) ||
        is<Artboard>())
    {
        return Vec2D();
    }
    return originOffset();
}

Vec2D LayoutComponent::originOffset() const
{
    return Vec2D(pivotOriginX() * m_layout.width(),
                 pivotOriginY() * m_layout.height());
}

Vec2D LayoutComponent::layoutTranslation() const
{
    // Our own origin deliberately does not enter here: contents sit within
    // our box whatever it is, so nothing inside has to compensate. An
    // artboard's origin does define where its local zero sits, so step back
    // by it to align to its box.
    auto location = Vec2D(m_layout.left(), m_layout.top());
    if (parent() != nullptr && parent()->is<Artboard>())
    {
        auto art = parent()->as<Artboard>();
        location -= Vec2D(art->layoutWidth() * art->originX(),
                          art->layoutHeight() * art->originY());
    }
    return location;
}

Mat2D LayoutComponent::buildOwnTransform() const
{
    // Outermost, matching TransformComponent's T * R * S, so the offset is
    // not rotated or scaled by our own transform.
    Mat2D own =
        composesLayoutOffset()
            ? Mat2D::fromTranslation(Vec2D(NodeBase::x(), NodeBase::y()))
            : Mat2D();

    // Pivot about the origin. The box stays put, so wrap rather than fold
    // into the frame.
    if (hasLayoutFlag(LayoutComponentFlags::ComposeTransform) &&
        (rotation() != 0.0f || scaleX() != 1.0f || scaleY() != 1.0f))
    {
        Mat2D local =
            rotation() != 0.0f ? Mat2D::fromRotation(rotation()) : Mat2D();
        local.scaleByValues(scaleX(), scaleY());
        auto pivot = originOffset();
        if (pivot.x != 0.0f || pivot.y != 0.0f)
        {
            local = Mat2D::multiply(
                Mat2D::fromTranslate(pivot.x, pivot.y),
                Mat2D::multiply(local,
                                Mat2D::fromTranslate(-pivot.x, -pivot.y)));
        }
        own = Mat2D::multiply(own, local);
    }
    return own;
}

// Same unrooted guard as Node's — nothing to be relative to yet.
float LayoutComponent::computedRootX()
{
    if (artboard() == nullptr)
    {
        return 0.0f;
    }
    return artboard()->rootTransform(worldTransform() * localAnchor()).x;
}

float LayoutComponent::computedRootY()
{
    if (artboard() == nullptr)
    {
        return 0.0f;
    }
    return artboard()->rootTransform(worldTransform() * localAnchor()).y;
}

void LayoutComponent::updateTransform() { m_Transform = buildOwnTransform(); }

void LayoutComponent::composeWorldTransform()
{
    Mat2D parentWorld =
        parent() != nullptr && parent()->is<WorldTransformComponent>()
            ? parent()->as<WorldTransformComponent>()->worldTransform()
            : Mat2D();
    // Insert where the layout placed us, the same shape Shape/Text/Image
    // use for a participant.
    Mat2D base = Mat2D::fromTranslation(layoutTranslation());
    m_WorldTransform =
        Mat2D::multiply(Mat2D::multiply(parentWorld, base), m_Transform);
}

void LayoutComponent::update(ComponentDirt value)
{
    Super::update(value);
#ifdef WITH_RIVE_LAYOUT
    if (value == ComponentDirt::Filthy)
    {
        // Use this to prevent layout animation on startup
        interruptAnimation();
    }
#endif
    if (hasDirt(value, ComponentDirt::RenderOpacity))
    {
        propagateOpacity(childOpacity());
    }
    if (parent() != nullptr && hasDirt(value, ComponentDirt::WorldTransform))
    {
        // Not left to Super's Transform-dirt pass: the pivot scales by the
        // solved size, so a re-solve alone can stale it.
        m_Transform = buildOwnTransform();
        composeWorldTransform();
        updateConstraints();
    }
    if (hasDirt(value,
                ComponentDirt::Path | ComponentDirt::WorldTransform |
                    ComponentDirt::LayoutStyle))
    {
        updateRenderPath();
    }

    setLayoutFlag(LayoutComponentFlags::PositionLeftChanged, false);
    setLayoutFlag(LayoutComponentFlags::PositionTopChanged, false);
}

void LayoutComponent::widthOverride(float width, int unitValue, bool isRow)
{
    m_widthOverride = width;
    m_widthUnitValueOverride = static_cast<int8_t>(unitValue);
    setLayoutFlag(LayoutComponentFlags::ParentIsRow, isRow);
    markLayoutNodeDirty();
}

void LayoutComponent::heightOverride(float height, int unitValue, bool isRow)
{
    m_heightOverride = height;
    m_heightUnitValueOverride = static_cast<int8_t>(unitValue);
    setLayoutFlag(LayoutComponentFlags::ParentIsRow, isRow);
    markLayoutNodeDirty();
}

void LayoutComponent::parentIsRow(bool isRow)
{
    setLayoutFlag(LayoutComponentFlags::ParentIsRow, isRow);
    markLayoutNodeDirty();
}

#ifdef WITH_RIVE_LAYOUT
LayoutScaleType LayoutComponent::effectiveWidthScaleType()
{
    if (canHaveOverrides() && m_widthUnitValueOverride != -1)
    {
        switch (YGUnit(m_widthUnitValueOverride))
        {
            case YGUnitPoint:
            case YGUnitPercent:
                return LayoutScaleType::fixed;
            case YGUnitAuto:
                return hasLayoutFlag(
                           LayoutComponentFlags::WidthIntrinsicallySizeOverride)
                           ? LayoutScaleType::hug
                           : LayoutScaleType::fill;
            default:
                break;
        }
    }
    return m_style != nullptr ? m_style->widthScaleType()
                              : LayoutScaleType::fixed;
}

LayoutScaleType LayoutComponent::effectiveHeightScaleType()
{
    if (canHaveOverrides() && m_heightUnitValueOverride != -1)
    {
        switch (YGUnit(m_heightUnitValueOverride))
        {
            case YGUnitPoint:
            case YGUnitPercent:
                return LayoutScaleType::fixed;
            case YGUnitAuto:
                return hasLayoutFlag(LayoutComponentFlags::
                                         HeightIntrinsicallySizeOverride)
                           ? LayoutScaleType::hug
                           : LayoutScaleType::fill;
            default:
                break;
        }
    }
    return m_style != nullptr ? m_style->heightScaleType()
                              : LayoutScaleType::fixed;
}
#endif

void LayoutComponent::parentIsStack(bool isStack)
{
    if (hasLayoutFlag(LayoutComponentFlags::ParentIsStack) == isStack)
    {
        return;
    }
    setLayoutFlag(LayoutComponentFlags::ParentIsStack, isStack);
    markLayoutNodeDirty();
}

void LayoutComponent::widthIntrinsicallySizeOverride(bool intrinsic)
{
    setLayoutFlag(LayoutComponentFlags::WidthIntrinsicallySizeOverride,
                  intrinsic);
    // If we have an intrinsically sized override, set units to auto
    // otherwise set to points
    m_widthUnitValueOverride = intrinsic ? 3 : 1;
    markLayoutNodeDirty();
}

void LayoutComponent::heightIntrinsicallySizeOverride(bool intrinsic)
{
    setLayoutFlag(LayoutComponentFlags::HeightIntrinsicallySizeOverride,
                  intrinsic);
    // If we have an intrinsically sized override, set units to auto
    // otherwise set to points
    m_heightUnitValueOverride = intrinsic ? 3 : 1;
    markLayoutNodeDirty();
}

void LayoutComponent::forcedWidth(float width)
{
    if (m_forcedWidth == width)
    {
        return;
    }
    m_forcedWidth = width;
    markLayoutStyleDirty();
    markLayoutNodeDirty();
}

void LayoutComponent::forcedHeight(float height)
{
    if (m_forcedHeight == height)
    {
        return;
    }
    m_forcedHeight = height;
    markLayoutStyleDirty();
    markLayoutNodeDirty();
}

void LayoutComponent::updateConstraints()
{
    if (layoutConstraints().size() > 0)
    {
        for (auto parentConstraint : layoutConstraints())
        {
            parentConstraint->constrainChild(this);
        }
    }
    Super::updateConstraints();
}

bool LayoutComponent::overridesKeyedInterpolation(int propertyKey)
{
#ifdef WITH_RIVE_LAYOUT
    if (animates())
    {
        switch (propertyKey)
        {
            case LayoutComponentBase::widthPropertyKey:
            case LayoutComponentBase::heightPropertyKey:
                return true;
            default:
                return false;
        }
    }
#endif
    return false;
}

bool LayoutComponent::isHidden() const
{
    return Super::isHidden() || isCollapsed();
}

bool LayoutComponent::isCollapsed() const
{
    if (Super::isCollapsed())
    {
        return true;
    }
#ifdef WITH_RIVE_LAYOUT
    return styleDisplayHidden();
#endif
    return false;
}

void LayoutComponent::propagateCollapse(bool collapse)
{
    auto collapsed = collapse || isCollapsed();
    for (Component* child : children())
    {
        child->collapse(collapsed);
    }
    updateCollapsables();
}

bool LayoutComponent::collapse(bool value)
{
    if (!Component::collapse(value))
    {
        return false;
    }
    propagateCollapse(value);
    return true;
}

#ifdef WITH_RIVE_LAYOUT

LayoutComponent::LayoutComponent() : m_layoutData(new LayoutData())
{
    m_layoutData->node.getConfig()->setPointScaleFactor(0);
}

float LayoutComponent::gapHorizontal()
{
    if (m_style == nullptr)
    {
        return 0;
    }
    return m_style->gapHorizontalUnits() == YGUnitPercent
               ? (m_style->gapHorizontal() / 100.0f) * layoutWidth()
               : m_style->gapHorizontal();
}

float LayoutComponent::gapVertical()
{
    if (m_style == nullptr)
    {
        return 0;
    }
    return m_style->gapVerticalUnits() == YGUnitPercent
               ? (m_style->gapVertical() / 100.0f) * layoutHeight()
               : m_style->gapVertical();
}

StatusCode LayoutComponent::onAddedDirty(CoreContext* context)
{
    auto code = Super::onAddedDirty(context);
    if (code != StatusCode::Ok)
    {
        return code;
    }

    auto coreStyle = context->resolve(styleId());
    if (coreStyle == nullptr || !coreStyle->is<LayoutComponentStyle>())
    {
        return StatusCode::MissingObject;
    }
    m_style = static_cast<LayoutComponentStyle*>(coreStyle);
    addChild(m_style);
#ifdef WITH_RIVE_LAYOUT
    // We contribute sizing the style cannot see; it contributes the rest.
    addLayoutStyleApplier(this);
    addLayoutStyleApplier(m_style);
#endif

    return StatusCode::Ok;
}

StatusCode LayoutComponent::onAddedClean(CoreContext* context)
{
    auto code = Super::onAddedClean(context);
    if (code != StatusCode::Ok)
    {
        return code;
    }
#ifdef WITH_RIVE_EDITOR
    // Coop-apply hydration: skip the render/layout side effects — the
    // graph is partial here and they re-fire when the renderer attaches
    // and the first pump runs. Runtime .riv imports are marked validated
    // at read time and never see a pump, so they must run the wiring now
    // or Yoga layout stays NaN.
    if (hasValidated())
#endif
    {
        markLayoutStyleDirty();
        syncLayoutChildren();
        propagateCollapse(isCollapsed());
    }
    return StatusCode::Ok;
}

void LayoutComponent::drawProxy(Renderer* renderer)
{
    // Pair the save/clip here with the restore in draw(). Record whether we
    // actually saved so draw() never restores a save that wasn't issued. Set OR
    // clear it every time the proxy draws: the proxy is injected once and stays
    // in the draw order, so a later pass where clip() is off must clear a stale
    // true from an earlier pass. (When the proxy isn't in the draw order at
    // all, this never runs, the flag stays false, and draw() skips the
    // restore.)
    const bool saveForClip = clip();
    if (saveForClip)
    {
        renderer->save();
        renderer->clipPath(mutableRenderPaths().world.renderPath(this));
    }
    setLayoutFlag(LayoutComponentFlags::ClipSaved, saveForClip);
    for (auto shapePaint : m_ShapePaints)
    {
        if (!shapePaint->shouldDraw())
        {
            continue;
        }
        auto shapePaintPath = shapePaint->pickPath(this);
        if (shapePaintPath == nullptr)
        {
            continue;
        }
        shapePaint->draw(renderer, shapePaintPath, worldTransform());
    }
}

void LayoutComponent::draw(Renderer* renderer)
{
    // Restore clip before drawing stroke so we don't clip the stroke. Pair the
    // restore with drawProxy()'s save via ClipSaved rather than clip(): if the
    // proxy wasn't in the draw order (so drawProxy() never saved) but clip() is
    // true, restoring here would underflow the renderer's save stack.
    if (hasLayoutFlag(LayoutComponentFlags::ClipSaved))
    {
        setLayoutFlag(LayoutComponentFlags::ClipSaved, false);
        renderer->restore();
    }
}

void LayoutComponent::updateRenderPath()
{
    if (isHidden())
    {
        return;
    }
    if (m_ShapePaints.empty() && !clip() &&
        !hasLayoutFlag(LayoutComponentFlags::HasForegroundDrawable))
    {
        return;
    }
    float tl = 0.0f, tr = 0.0f, br = 0.0f, bl = 0.0f;
    if (style() != nullptr)
    {
        const bool isLTR = actualDirection() != LayoutDirection::rtl;
        if (style()->linkCornerRadius())
        {
            tl = tr = br = bl = style()->cornerRadiusTL();
        }
        else
        {
            tl = isLTR ? style()->cornerRadiusTL() : style()->cornerRadiusTR();
            tr = isLTR ? style()->cornerRadiusTR() : style()->cornerRadiusTL();
            bl = isLTR ? style()->cornerRadiusBL() : style()->cornerRadiusBR();
            br = isLTR ? style()->cornerRadiusBR() : style()->cornerRadiusBL();
        }
    }

    auto& renderPaths = mutableRenderPaths();
    renderPaths.background.rewind();
    Path::addRoundedRect(
        renderPaths.background,
        AABB::fromLTWH(0.0f, 0.0f, m_layout.width(), m_layout.height()),
        tl,
        tr,
        br,
        bl);

    renderPaths.local.rewind();
    renderPaths.local.addPath(renderPaths.background);

    renderPaths.world.rewind(false, FillRule::clockwise);
    renderPaths.world.addPath(renderPaths.background, &m_WorldTransform);

    for (auto shapePaint : m_ShapePaints)
    {
        if (!shapePaint->shouldDraw())
        {
            continue;
        }
        if (shapePaint->is<ShapePaint>())
        {
            shapePaint->as<ShapePaint>()->invalidateEffects();
        }
    }
}

static YGSize measureFunc(YGNode* node,
                          float width,
                          YGMeasureMode widthMode,
                          float height,
                          YGMeasureMode heightMode)
{
    const bool probing = YGConfigIsMeasuringMinContent(node->getConfig());
    Vec2D size =
        ((LayoutComponent*)node->getContext())
            ->measureLayout(width,
                            measureModeForContent((LayoutMeasureMode)widthMode,
                                                  width,
                                                  probing),
                            height,
                            measureModeForContent((LayoutMeasureMode)heightMode,
                                                  height,
                                                  probing));

    return YGSize{size.x, size.y};
}

Vec2D LayoutComponent::measureLayout(float width,
                                     LayoutMeasureMode widthMode,
                                     float height,
                                     LayoutMeasureMode heightMode)
{
    if (m_style != nullptr && m_style->hugUnbounded())
    {
        // Per axis: a fill axis leaves flexBasis auto, so its measure feeds
        // yoga's basis for the line. Widening it there would move this item's
        // share of the remainder -- a fill axis the option never promised to
        // touch.
        bool widthHugs = effectiveWidthScaleType() == LayoutScaleType::hug;
        bool heightHugs = effectiveHeightScaleType() == LayoutScaleType::hug;
        // Legacy files encode hug as fixed on BOTH axes plus
        // intrinsicallySized.
        if (!widthHugs && !heightHugs)
        {
            widthHugs = heightHugs = m_style->intrinsicallySized();
        }
        if (widthHugs)
        {
            widthMode = unboundMeasureMode(widthMode);
        }
        if (heightHugs)
        {
            heightMode = unboundMeasureMode(heightMode);
        }
    }
    Vec2D size = Vec2D();
    for (auto child : children())
    {
        if (child->is<LayoutComponent>())
        {
            continue;
        }
        auto sizeableChild = IntrinsicallySizeable::from(child);
        if (sizeableChild != nullptr)
        {
            Vec2D measured = sizeableChild->measureLayout(width,
                                                          widthMode,
                                                          height,
                                                          heightMode);
            size = Vec2D(std::max(size.x, measured.x),
                         std::max(size.y, measured.y));
        }
    }
    return size;
}

bool LayoutComponent::effectiveParentIsRow()
{
    if (canHaveOverrides())
    {
        return hasLayoutFlag(LayoutComponentFlags::ParentIsRow);
    }
    return layoutParent() != nullptr ? layoutParent()->mainAxisIsRow() : true;
}

bool LayoutComponent::mainAxisIsRow()
{
    if (style() == nullptr)
    {
        return true;
    }
    return style()->flexDirection() == YGFlexDirectionRow ||
           style()->flexDirection() == YGFlexDirectionRowReverse;
}

bool LayoutComponent::mainAxisIsColumn()
{
    if (style() == nullptr)
    {
        return false;
    }
    return style()->flexDirection() == YGFlexDirectionColumn ||
           style()->flexDirection() == YGFlexDirectionColumnReverse;
}

bool LayoutComponent::isStackContainer()
{
    return style() != nullptr && style()->isStack();
}

bool LayoutComponent::isLeaf()
{
    bool leaf = true;
    forEachLayoutProvider(this, [&leaf](Component*, LayoutNodeProvider*) {
        leaf = false;
    });
    return leaf;
}

void* LayoutComponent::layoutNode(int index)
{
    if (m_layoutData != nullptr)
    {
        return static_cast<void*>(&m_layoutData->node);
    }
    return nullptr;
}

#ifdef WITH_RIVE_LAYOUT
// Tracks come from GridTrack children, which the style cannot walk. A stack has
// no authored tracks — the style sets up its implicit cell instead.
void LayoutComponent::applyContainerStyle(YGStyle& ygStyle,
                                          const LayoutSyncContext& context)
{
    if (m_style == nullptr || m_style->isStack())
    {
        return;
    }
    GridTrack::syncContainerStyle(ygStyle, this, m_style->justifyItemsValue());
}
#endif

#ifdef WITH_RIVE_LAYOUT
// This layout's own size and how it sits in its parent's flow. On the
// component, not the style, because it reads width()/height(), the
// NestedArtboardLayout overrides and the forced dimensions.
//
// Not shared with LayoutParticipant::applyBaseStyle: the participant has no
// flexBasis, no overrides and its own fractionalWidth, so merging would change
// behaviour.
void LayoutComponent::applyBaseStyle(YGStyle& ygStyle,
                                     const LayoutSyncContext& context)
{
    if (m_style == nullptr)
    {
        return;
    }
    const bool parentIsRow = context.parentIsRow;
    const bool parentIsGridLike = context.parentIsGrid;

    // Derive the unit the layout engine needs from the persisted unit + scale
    // type.
    //   - fill/hug always map to YGUnitAuto (regardless of position type) —
    //     these scale modes don't have a meaningful unit; the layout engine
    //     decides the size.
    //   - fixed uses the stored unit. Absolute layouts trust whatever's
    //     stored (e.g. the editor freezes a point value at the moment
    //     positionType becomes absolute, since absolute children sit outside
    //     flex flow).
    bool isAbsolute = m_style->positionType() == YGPositionTypeAbsolute;
    bool isLegacyHugEncoding =
        m_style->widthScaleType() == LayoutScaleType::fixed &&
        m_style->heightScaleType() == LayoutScaleType::fixed &&
        m_style->intrinsicallySized() && isLeaf();
    auto effectiveUnits = [isAbsolute,
                           isLegacyHugEncoding](LayoutScaleType scaleType,
                                                YGUnit storedUnits) {
        if (isAbsolute && scaleType != LayoutScaleType::hug)
        {
            return storedUnits;
        }
        if (scaleType != LayoutScaleType::fixed)
        {
            return YGUnitAuto;
        }
        if (storedUnits == YGUnitPoint || storedUnits == YGUnitPercent)
        {
            return storedUnits;
        }
        return isLegacyHugEncoding ? YGUnitAuto : YGUnitPoint;
    };
    auto realWidth = width();
    auto realWidthScaleType = m_style->widthScaleType();
    auto realWidthUnits =
        effectiveUnits(realWidthScaleType, m_style->widthUnits());
    auto realHeight = height();
    auto realHeightScaleType = m_style->heightScaleType();
    auto realHeightUnits =
        effectiveUnits(realHeightScaleType, m_style->heightUnits());

    // If we have override width/height values, use those.
    // Currently we only use these for Artboards that are part of a
    // NestedArtboardLayout but perhaps there will be other use cases for
    // overriding in the future?
    if (canHaveOverrides())
    {
        if (!std::isnan(m_widthOverride))
        {
            realWidth = m_widthOverride;
        }
        if (!std::isnan(m_heightOverride))
        {
            realHeight = m_heightOverride;
        }
        if (m_widthUnitValueOverride != -1)
        {
            realWidthUnits = YGUnit(m_widthUnitValueOverride);
            realWidthScaleType = effectiveWidthScaleType();
        }
        if (m_heightUnitValueOverride != -1)
        {
            realHeightUnits = YGUnit(m_heightUnitValueOverride);
            realHeightScaleType = effectiveHeightScaleType();
        }
    }
    if (!std::isnan(m_forcedWidth))
    {
        ygStyle.dimensions()[YGDimensionWidth] =
            YGValue{std::max(0.0f, m_forcedWidth), YGUnitPoint};
    }
    else
    {
        ygStyle.dimensions()[YGDimensionWidth] =
            YGValue{std::max(0.0f, realWidth), realWidthUnits};
    }
    if (!std::isnan(m_forcedHeight))
    {
        ygStyle.dimensions()[YGDimensionHeight] =
            YGValue{std::max(0.0f, m_forcedHeight), YGUnitPoint};
    }
    else
    {
        ygStyle.dimensions()[YGDimensionHeight] =
            YGValue{std::max(0.0f, realHeight), realHeightUnits};
    }

    if (parentIsGridLike)
    {
        // Grid/stack: size per-axis. fill stretches that axis (width ->
        // justifySelf after grid placement below, height -> alignSelf);
        // non-fill stays auto so the container alignment positions us. flexGrow
        // ignored.
        ygStyle.flexGrow() = YGFloatOptional(0);
        ygStyle.flexShrink() = YGFloatOptional(0);
        ygStyle.alignSelf() = realHeightScaleType == LayoutScaleType::fill
                                  ? YGAlignStretch
                                  : YGAlignAuto;
    }
    else
    {
        switch (realWidthScaleType)
        {
            case LayoutScaleType::fixed:
                if (parentIsRow)
                {
                    ygStyle.flexGrow() = YGFloatOptional(0);
                    ygStyle.flexShrink() = YGFloatOptional(0);
                    ygStyle.flexBasis() =
                        YGValue{m_style->flexBasis(), YGUnitAuto};
                }
                else
                {
                    ygStyle.alignSelf() = YGAlignAuto;
                }
                break;
            case LayoutScaleType::fill:
                if (parentIsRow)
                {
                    ygStyle.flexGrow() = YGFloatOptional(fractionalWidth());
                    ygStyle.flexShrink() = YGFloatOptional(fractionalWidth());
                    ygStyle.flexBasis() = YGValue{m_style->flexBasis(),
                                                  m_style->flexBasisUnits()};
                }
                else
                {
                    ygStyle.alignSelf() = YGAlignStretch;
                }
                break;
            case LayoutScaleType::hug:
                if (parentIsRow)
                {
                    ygStyle.flexGrow() = YGFloatOptional(0);
                    ygStyle.flexShrink() = YGFloatOptional(0);
                    ygStyle.flexBasis() =
                        YGValue{m_style->flexBasis(), YGUnitAuto};
                }
                else
                {
                    ygStyle.alignSelf() = YGAlignAuto;
                }
                break;
            default:
                break;
        }

        switch (realHeightScaleType)
        {
            case LayoutScaleType::fixed:
                if (!parentIsRow)
                {
                    ygStyle.flexGrow() = YGFloatOptional(0);
                    ygStyle.flexShrink() = YGFloatOptional(0);
                    ygStyle.flexBasis() =
                        YGValue{m_style->flexBasis(), YGUnitAuto};
                }
                else
                {
                    ygStyle.alignSelf() = YGAlignAuto;
                }
                break;
            case LayoutScaleType::fill:
                if (!parentIsRow)
                {
                    ygStyle.flexGrow() = YGFloatOptional(fractionalHeight());
                    ygStyle.flexShrink() = YGFloatOptional(fractionalHeight());
                    ygStyle.flexBasis() = YGValue{m_style->flexBasis(),
                                                  m_style->flexBasisUnits()};
                }
                else
                {
                    ygStyle.alignSelf() = YGAlignStretch;
                }
                break;
            case LayoutScaleType::hug:
                if (!parentIsRow)
                {
                    ygStyle.flexGrow() = YGFloatOptional(0);
                    ygStyle.flexShrink() = YGFloatOptional(0);
                    ygStyle.flexBasis() =
                        YGValue{m_style->flexBasis(), YGUnitAuto};
                }
                else
                {
                    ygStyle.alignSelf() = YGAlignAuto;
                }
                break;
            default:
                break;
        }
    }
}
#endif

void LayoutComponent::syncStyle()
{
    if (m_style == nullptr || m_layoutData == nullptr)
    {
        return;
    }
    YGNode& ygNode = m_layoutData->node;
    // Appliers write straight into the node's own style; no scratch copy.
    YGStyle& ygStyle = m_layoutData->style();
    if (m_style->intrinsicallySized() && isLeaf())
    {
        ygNode.setContext(this);
        ygNode.setMeasureFunc(measureFunc);
    }
    else
    {
        ygNode.setMeasureFunc(nullptr);
    }

    // Our owning layout may sit above a transparent container (group/Solo), so
    // walk up for it rather than reading the immediate parent — a grouped item
    // is still laid out by the container and needs its context. Cached because
    // layoutParent() walks the chain on each call.
    auto* parentLayout = layoutParent();
    auto* parentLayoutStyle =
        parentLayout != nullptr ? parentLayout->style() : nullptr;
    // A hosted artboard (list item, nested artboard layout) has no parent() to
    // walk, so its host pushes the container's stack state in. Only stack is
    // pushed: a grid already auto-places these nodes correctly, and claiming
    // grid here would move them off the flex sizing path they use today.
    bool parentIsStack =
        parentLayoutStyle != nullptr
            ? parentLayoutStyle->isStack()
            : (canHaveOverrides() &&
               hasLayoutFlag(LayoutComponentFlags::ParentIsStack));
    bool parentIsGridLike = parentLayoutStyle != nullptr
                                ? parentLayoutStyle->isGrid()
                                : parentIsStack;
    uint32_t containerJustifyItems =
        parentLayoutStyle != nullptr ? parentLayoutStyle->justifyItemsValue()
                                     : (uint32_t)YGJustifyStretch;
    // Every style write is an applier now; resolve the context and run them.
    LayoutSyncContext syncContext;
    syncContext.parentIsGrid = parentIsGridLike;
    syncContext.parentIsStack = parentIsStack;
    syncContext.containerJustifyItems = containerJustifyItems;
    auto widthScale = effectiveWidthScaleType();
    syncContext.widthFills = widthScale == LayoutScaleType::fill;
    syncContext.inlineHugs = widthScale == LayoutScaleType::hug;
    syncContext.parentIsRow = effectiveParentIsRow();
    syncContext.isLTR = actualDirection() != LayoutDirection::rtl;
    syncContext.hasLayoutParent = layoutParent() != nullptr;
    m_layoutData->applyLayoutStyles(ygStyle, syncContext);

    // Sync the styles of participant children that provide their
    // own layout node (including any nested inside transparent groups).
    // LayoutComponent children sync their own styles through the dirty-layout
    // set; these have no such entry.
    forEachLayoutProvider(this,
                          [](Component* child, LayoutNodeProvider* provider) {
                              switch (child->coreType())
                              {
                                  case LayoutComponentBase::typeKey:
                                  case NestedArtboardLayoutBase::typeKey:
                                  case ArtboardComponentListBase::typeKey:
                                      break;
                                  default:
                                      provider->syncStyleChanges();
                                      break;
                              }
                          });
}

void LayoutComponent::clearLayoutChildren()
{
    YGNode& ourNode = m_layoutData->node;
    YGNodeRemoveAllChildren(&ourNode);
}

void LayoutComponent::syncLayoutChildren()
{
    YGNode& ourNode = m_layoutData->node;
    YGNodeRemoveAllChildren(&ourNode);
    int index = 0;
    forEachLayoutProvider(
        this,
        [&ourNode, &index](Component*, LayoutNodeProvider* provider) {
            for (size_t i = 0; i < provider->numLayoutNodes(); i++)
            {
                auto* node = static_cast<YGNode*>(provider->layoutNode((int)i));
                if (node != nullptr)
                {
                    ourNode.insertChild(node, index++);
                    node->setOwner(&ourNode);
                    ourNode.markDirtyAndPropagate();
                }
            }
        });
    markLayoutNodeDirty();
}

#ifdef WITH_RIVE_TOOLS
bool LayoutComponent::collectsForLayout(Component* child)
{
    // Runs the real walk rather than a copy of the rule.
    bool found = false;
    forEachLayoutProvider(this,
                          [child, &found](Component* c, LayoutNodeProvider*) {
                              if (c == child)
                              {
                                  found = true;
                              }
                          });
    return found;
}
#endif

void LayoutComponent::propagateSize() { propagateSizeToChildren(this); }

void LayoutComponent::propagateSizeToChildren(ContainerComponent* component)
{
    if (isHidden())
    {
        return;
    }
    for (auto child : component->children())
    {
        // Don't content-size nested layouts, or groups — a group's contents are
        // free content, never content-sized from here. A Solo is not a barrier:
        // its children content-size as direct children would. A participating
        // child is caught by the provider check below.
        if (child->is<LayoutComponent>() || stopsContentSizing(child))
        {
            continue;
        }
        // A participating child owns its own layout node and is sized by the
        // layout engine, not by controlSize — skip it.
        if (LayoutNodeProvider::from(child) != nullptr)
        {
            continue;
        }
        auto sizeableChild = IntrinsicallySizeable::from(child);
        if (sizeableChild != nullptr && m_style != nullptr)
        {
            LayoutScaleType widthScaleType = m_style->widthScaleType();
            LayoutScaleType heightScaleType = m_style->heightScaleType();
            sizeableChild->controlSize(
                Vec2D(m_layout.width(), m_layout.height()),
                widthScaleType,
                heightScaleType,
                actualDirection());

            if (!sizeableChild->shouldPropagateSizeToChildren())
            {
                // Do not propagate to its children
                continue;
            }
        }
        if (child->is<ContainerComponent>())
        {
            propagateSizeToChildren(child->as<ContainerComponent>());
        }
    }
}

void LayoutComponent::calculateLayoutInternal(float availableWidth,
                                              float availableHeight)
{
    auto actualAvailWidth =
        std::isnan(availableWidth) && m_style && m_style->intrinsicallySized()
            ? availableWidth
            : width();
    auto actualAvailHeight =
        std::isnan(availableHeight) && m_style && m_style->intrinsicallySized()
            ? availableHeight
            : height();
    YGNodeCalculateLayout(&m_layoutData->node,
                          actualAvailWidth,
                          actualAvailHeight,
                          YGDirection::YGDirectionInherit);
}

bool LayoutComponent::styleDisplayHidden() const
{
    if (m_style == nullptr)
    {
        return false;
    }
    return m_style->display() == YGDisplayNone;
}

LayoutDirection LayoutComponent::actualDirection()
{
    if (m_style == nullptr)
    {
        return m_inheritedDirection;
    }
    switch (m_style->direction())
    {
        case YGDirectionLTR:
            return LayoutDirection::ltr;
        case YGDirectionRTL:
            return LayoutDirection::rtl;
        default:
            return m_inheritedDirection;
    }
}

void LayoutComponent::onDirty(ComponentDirt value)
{
    Super::onDirty(value);
    if ((value & ComponentDirt::WorldTransform) ==
            ComponentDirt::WorldTransform &&
        clip())
    {
        addDirt(ComponentDirt::Path);
    }
}

static Layout layoutFromYoga(const YGLayout& layout)
{
    return Layout(layout.position[YGEdgeLeft],
                  layout.position[YGEdgeTop],
                  layout.dimensions[YGDimensionWidth],
                  layout.dimensions[YGDimensionHeight]);
}

static LayoutPadding layoutPaddingFromYoga(const YGLayout& layout)
{
    return LayoutPadding(layout.padding[YGEdgeLeft],
                         layout.padding[YGEdgeTop],
                         layout.padding[YGEdgeRight],
                         layout.padding[YGEdgeBottom]);
}

void LayoutComponent::updateLayoutBounds(bool animate)
{
    YGNode& node = m_layoutData->node;
    bool updated = node.getHasNewLayout();
    if (!updated)
    {
        return;
    }
    node.setHasNewLayout(false);

    forEachLayoutProvider(this,
                          [animate](Component*, LayoutNodeProvider* provider) {
                              provider->updateLayoutBounds(animate);
                          });

    const auto& yogaLayout = node.getLayout();
    Layout newLayout = layoutFromYoga(yogaLayout);
    m_layoutPadding = layoutPaddingFromYoga(yogaLayout);

    if (hasLayoutFlag(LayoutComponentFlags::JustAddedToHost))
    {
        setLayoutFlag(LayoutComponentFlags::JustAddedToHost, false);
        // In cases were we have a host (ie, Component List, etc), we
        // don't want to animate the x/y/width/height because the initial
        // x/y/width/height will have been 0,0,0,0 within the parent host.
        //
        // Instead, we want to the position/size to start at whatever this
        // layout's computed position is within its host.
        //
        // We'll keep this as an entirely seperate code path because
        // this may be useful in adding support for animate in/out of
        // items in an ArtboardHost.
        m_layout = newLayout;
        // Unallocated, from/to already read as m_layout, which we just set --
        // there is nothing to snap.
        if (auto* animationData = currentAnimationData())
        {
            animationData->from = newLayout;
            animationData->to = newLayout;
            animationData->elapsedSeconds = 0.0f;
        }
        propagateSize();
        markWorldTransformDirty();
        setLayoutFlag(LayoutComponentFlags::ForceUpdateLayoutBounds, false);
        return;
    }

    if (animate && animates())
    {
        // Test the target before allocating: with no state the target reads
        // as m_layout, so a layout that solves to the bounds it already has
        // never pays for the block just because its style can animate.
        auto animationData = currentAnimationData();
        const Layout& target =
            animationData != nullptr ? animationData->to : m_layout;
        if (newLayout != target ||
            hasLayoutFlag(LayoutComponentFlags::ForceUpdateLayoutBounds))
        {
            // Committed to retargeting now, so realize the state.
            ensureAnimation();
            animationData = currentAnimationData();
            if (animationData->elapsedSeconds != 0.0f)
            {
                if (hasLayoutFlag(LayoutComponentFlags::IsSmoothingAnimation))
                {
                    // we were already smoothening.
                    m_animation->a.copy(m_animation->b);
                }
                setLayoutFlag(LayoutComponentFlags::IsSmoothingAnimation, true);
            }
            else
            {
                setLayoutFlag(LayoutComponentFlags::IsSmoothingAnimation,
                              false);
            }
            animationData = currentAnimationData();
            animationData->from = m_layout;
            animationData->to = newLayout;
            animationData->elapsedSeconds = 0.0f;
            propagateSize();
            markWorldTransformDirty();
        }
    }
    else if (newLayout != m_layout ||
             hasLayoutFlag(LayoutComponentFlags::ForceUpdateLayoutBounds))
    {
        if (m_layout.width() != newLayout.width() ||
            m_layout.height() != newLayout.height())
        {
            // Width changed, we need to rebuild the path.
            addDirt(ComponentDirt::Path);
        }
        m_layout = newLayout;
        if (m_animation != nullptr)
        {
            // Keep the animate path's retarget check honest: while we are not
            // animating, `to` tracks m_layout (which is what the unallocated
            // case reports anyway).
            m_animation->a.to = newLayout;
        }

        propagateSize();
        markWorldTransformDirty();
    }
    setLayoutFlag(LayoutComponentFlags::ForceUpdateLayoutBounds, false);
}

bool LayoutComponent::advanceComponent(float elapsedSeconds, AdvanceFlags flags)
{
    if ((flags & AdvanceFlags::NewFrame) != AdvanceFlags::NewFrame ||
        isCollapsed())
    {
        return false;
    }

    return applyInterpolation(elapsedSeconds,
                              (flags & AdvanceFlags::Animate) ==
                                      AdvanceFlags::Animate ||
                                  (flags & AdvanceFlags::AdvanceNested) ==
                                      AdvanceFlags::AdvanceNested);
}

bool LayoutComponent::animates()
{
    if (m_style == nullptr)
    {
        return false;
    }
    return m_style->animationStyle() != LayoutAnimationStyle::none &&
           interpolation() != LayoutStyleInterpolation::hold &&
           interpolationTime() > 0;
}

LayoutAnimationStyle LayoutComponent::animationStyle()
{
    if (m_style == nullptr)
    {
        return LayoutAnimationStyle::none;
    }
    return m_style->animationStyle();
}

KeyFrameInterpolator* LayoutComponent::interpolator()
{
    if (m_style == nullptr)
    {
        return nullptr;
    }
    switch (m_style->animationStyle())
    {
        case LayoutAnimationStyle::inherit:
        {
            auto* inherited = m_animation != nullptr
                                  ? m_animation->inheritedInterpolator
                                  : nullptr;
            return inherited != nullptr ? inherited : m_style->interpolator();
        }
        case LayoutAnimationStyle::custom:
            return m_style->interpolator();
        default:
            return nullptr;
    }
}

LayoutStyleInterpolation LayoutComponent::interpolation()
{
    auto defaultInterpolation = LayoutStyleInterpolation::hold;
    if (m_style == nullptr)
    {
        return defaultInterpolation;
    }
    switch (m_style->animationStyle())
    {
        case LayoutAnimationStyle::inherit:
            return m_animation != nullptr ? m_animation->inheritedInterpolation
                                          : defaultInterpolation;
        case LayoutAnimationStyle::custom:
            return m_style->interpolation();
        default:
            return defaultInterpolation;
    }
}

float LayoutComponent::interpolationTime()
{
    if (m_style == nullptr)
    {
        return 0;
    }
    switch (m_style->animationStyle())
    {
        case LayoutAnimationStyle::inherit:
            return m_animation != nullptr
                       ? m_animation->inheritedInterpolationTime
                       : 0;
        case LayoutAnimationStyle::custom:
            return m_style->interpolationTime();
        default:
            return 0;
    }
}

bool LayoutComponent::cascadeLayoutStyle(
    LayoutStyleInterpolation inheritedInterpolation,
    KeyFrameInterpolator* inheritedInterpolator,
    float inheritedInterpolationTime,
    LayoutDirection direction)
{
    bool updated = false;
    if (m_style != nullptr &&
        m_style->animationStyle() == LayoutAnimationStyle::inherit)
    {
        updated = setInheritedInterpolation(inheritedInterpolation,
                                            inheritedInterpolator,
                                            inheritedInterpolationTime);
    }
    else
    {
        clearInheritedInterpolation();
    }
    auto oldDirection = m_inheritedDirection;
    if (direction == LayoutDirection::inherit ||
        (m_style != nullptr && m_style->direction() != YGDirectionInherit))
    {
        m_inheritedDirection = LayoutDirection::inherit;
    }
    else
    {
        m_inheritedDirection = direction;
    }
    if (m_inheritedDirection != oldDirection)
    {
        markLayoutNodeDirty(true);
        addDirt(ComponentDirt::Path);
        updated = true;
    }
    forEachLayoutProvider(this,
                          [this](Component*, LayoutNodeProvider* provider) {
                              provider->cascadeLayoutStyle(interpolation(),
                                                           interpolator(),
                                                           interpolationTime(),
                                                           actualDirection());
                          });
    return updated;
}

bool LayoutComponent::setInheritedInterpolation(
    LayoutStyleInterpolation inheritedInterpolation,
    KeyFrameInterpolator* inheritedInterpolator,
    float inheritedInterpolationTime)
{
    if (m_animation == nullptr)
    {
        // An all-default cascade is what an unallocated layout already
        // reports, so storing it would change nothing but the footprint.
        if (inheritedInterpolation == LayoutStyleInterpolation::hold &&
            inheritedInterpolator == nullptr &&
            inheritedInterpolationTime == 0.0f)
        {
            return false;
        }
        ensureAnimation();
    }
    if (inheritedInterpolation != m_animation->inheritedInterpolation ||
        inheritedInterpolator != m_animation->inheritedInterpolator ||
        inheritedInterpolationTime != m_animation->inheritedInterpolationTime)
    {
        m_animation->inheritedInterpolation = inheritedInterpolation;
        m_animation->inheritedInterpolator = inheritedInterpolator;
        m_animation->inheritedInterpolationTime = inheritedInterpolationTime;
        return true;
    }
    return false;
}

void LayoutComponent::clearInheritedInterpolation()
{
    if (m_animation == nullptr)
    {
        // Already reporting the cleared values.
        return;
    }
    m_animation->inheritedInterpolation = LayoutStyleInterpolation::hold;
    m_animation->inheritedInterpolator = nullptr;
    m_animation->inheritedInterpolationTime = 0;
}

LayoutAnimationData* LayoutComponent::currentAnimationData()
{
    if (m_animation == nullptr)
    {
        return nullptr;
    }
    return hasLayoutFlag(LayoutComponentFlags::IsSmoothingAnimation)
               ? &m_animation->b
               : &m_animation->a;
}

LayoutAnimation& LayoutComponent::ensureAnimation()
{
    if (m_animation == nullptr)
    {
        m_animation = std::make_unique<LayoutAnimation>();
        // While unallocated the accessors report from/to as m_layout. Seed the
        // real state identically so realizing it is never observable -- in
        // particular the animate path's `newLayout != to` retarget check must
        // not fire just because we allocated.
        m_animation->a.from = m_animation->a.to = m_layout;
        m_animation->b.from = m_animation->b.to = m_layout;
    }
    return *m_animation;
}

void LayoutAnimationData::copy(const LayoutAnimationData& source)
{
    from = source.from;
    to = source.to;
    elapsedSeconds = source.elapsedSeconds;
}

bool LayoutComponent::applyInterpolation(float elapsedSeconds, bool animate)
{
    auto animationData = currentAnimationData();
    // No state means nothing was ever retargeted: `to` reads as m_layout, so
    // the original `to == m_layout` bail-out holds by construction.
    if (animationData == nullptr || !animate || !animates() ||
        m_style == nullptr || animationData->to == m_layout)
    {
        return false;
    }
    if (hasLayoutFlag(LayoutComponentFlags::IsSmoothingAnimation))
    {
        float f =
            std::fmin(1.0f,
                      interpolationTime() > 0.0f
                          ? m_animation->a.elapsedSeconds / interpolationTime()
                          : 1.0f);

        if (interpolation() != LayoutStyleInterpolation::linear &&
            interpolator() != nullptr)
        {
            f = interpolator()->transform(f);
        }
        m_animation->b.from = m_animation->a.interpolate(f);
        if (f == 1.0f)
        {
            m_animation->a.copy(m_animation->b);
            setLayoutFlag(LayoutComponentFlags::IsSmoothingAnimation, false);
        }
        else
        {
            m_animation->a.elapsedSeconds += elapsedSeconds;
        }
    }

    if ((animationData = currentAnimationData())->elapsedSeconds >=
        interpolationTime())
    {
        Layout newLayout = animationData->to;
        if (m_layout.width() != newLayout.width() ||
            m_layout.height() != newLayout.height())
        {
            addDirt(ComponentDirt::Path);
        }
        m_layout = animationData->to;

        if (hasLayoutFlag(LayoutComponentFlags::IsSmoothingAnimation))
        {
            setLayoutFlag(LayoutComponentFlags::IsSmoothingAnimation, false);
            m_animation->a.copy(m_animation->b);
            m_animation->a.elapsedSeconds = m_animation->b.elapsedSeconds =
                0.0f;
        }
        else
        {
            m_animation->a.elapsedSeconds = 0.0f;
        }
        propagateSize();
        markWorldTransformDirty();

        return false;
    }
    float f =
        std::fmin(1.0f,
                  interpolationTime() > 0
                      ? animationData->elapsedSeconds / interpolationTime()
                      : 1.0f);
    if (interpolation() != LayoutStyleInterpolation::linear &&
        interpolator() != nullptr)
    {
        f = interpolator()->transform(f);
    }

    auto current = animationData->interpolate(f);
    if (m_layout != current)
    {
        bool sizeChanged = m_layout.width() != current.width() ||
                           m_layout.height() != current.height();
        m_layout = current;
        if (sizeChanged)
        {
            propagateSize();
        }
        markWorldTransformDirty();
    }

    animationData->elapsedSeconds += elapsedSeconds;
    if (f != 1)
    {
        // Do we really need to mark the layout node dirty!!??
        markLayoutNodeDirty();
        return true;
    }
    return false;
}

void LayoutComponent::interruptAnimation()
{
    if (animates())
    {
        if (auto* animationData = currentAnimationData())
        {
            m_layout = animationData->to;
        }
        propagateSize();
    }
}

void LayoutComponent::markLayoutNodeDirty(bool shouldForceUpdateLayoutBounds)
{
    if (shouldForceUpdateLayoutBounds == true)
    {
        setLayoutFlag(LayoutComponentFlags::ForceUpdateLayoutBounds,
                      shouldForceUpdateLayoutBounds);
    }
    m_layoutData->node.markDirtyAndPropagate();
    artboard()->markLayoutDirty(this);
}

void LayoutComponent::markLayoutStyleDirty()
{
    clearInheritedInterpolation();
    addDirt(ComponentDirt::LayoutStyle);
    if (artboard() != this)
    {
        artboard()->markLayoutStyleDirty();
    }
}

void LayoutComponent::positionTypeChanged()
{
    if (m_style == nullptr)
    {
        return;
    }
    if (m_style->positionType() == YGPositionTypeAbsolute)
    {
        // Preserve computed position only if left/top were not explicitly keyed
        // this frame. If keyed, honor those values and only set units
        // appropriately.
        if (!hasLayoutFlag(LayoutComponentFlags::PositionLeftChanged))
        {
            m_style->positionLeft(layoutBounds().left());
        }
        if (!hasLayoutFlag(LayoutComponentFlags::PositionTopChanged))
        {
            m_style->positionTop(layoutBounds().top());
        }
        m_style->positionRight(0);
        m_style->positionBottom(0);
        m_style->positionLeftUnitsValue(YGUnitPoint);
        m_style->positionTopUnitsValue(YGUnitPoint);
        m_style->positionRightUnitsValue(YGUnitUndefined);
        m_style->positionBottomUnitsValue(YGUnitUndefined);
    }
    else
    {
        m_style->positionLeft(0);
        m_style->positionTop(0);
        m_style->positionRight(0);
        m_style->positionBottom(0);
        m_style->positionLeftUnitsValue(YGUnitUndefined);
        m_style->positionTopUnitsValue(YGUnitUndefined);
        m_style->positionRightUnitsValue(YGUnitUndefined);
        m_style->positionBottomUnitsValue(YGUnitUndefined);
    }
    markLayoutNodeDirty();
}

void LayoutComponent::scaleTypeChanged()
{
    if (m_style == nullptr)
    {
        return;
    }
    m_style->intrinsicallySizedValue(
        m_style->widthScaleType() == LayoutScaleType::hug ||
        m_style->heightScaleType() == LayoutScaleType::hug);
    markLayoutNodeDirty();
}

void LayoutComponent::displayChanged()
{
    if (m_style == nullptr)
    {
        return;
    }
    propagateCollapse(isCollapsed());
    markLayoutNodeDirty();
}

void LayoutComponent::syncChildProviderStyles()
{
    forEachLayoutProvider(this, [](Component*, LayoutNodeProvider* provider) {
        provider->syncStyleChanges();
        provider->markLayoutNodeDirty();
    });
}

void LayoutComponent::flexDirectionChanged()
{
    markLayoutNodeDirty();
    syncChildProviderStyles();
}

// Switching grid/flex/stack changes how each child's style maps to yoga.
void LayoutComponent::layoutTypeChanged()
{
    markLayoutNodeDirty();
    syncChildProviderStyles();
}

void LayoutComponent::directionChanged()
{
    markLayoutStyleDirty();
    markLayoutNodeDirty(true);
}
#else
LayoutComponent::LayoutComponent() : m_layoutData(new LayoutData()) {}

float LayoutComponent::gapHorizontal() { return 0; }
float LayoutComponent::gapVertical() { return 0; }

void LayoutComponent::drawProxy(Renderer* renderer) {}

void LayoutComponent::draw(Renderer* renderer) {}

void LayoutComponent::updateRenderPath() {}

Vec2D LayoutComponent::measureLayout(float width,
                                     LayoutMeasureMode widthMode,
                                     float height,
                                     LayoutMeasureMode heightMode)
{
    return Vec2D();
}

bool LayoutComponent::advanceComponent(float elapsedSeconds, AdvanceFlags flags)
{
    return false;
}

void LayoutComponent::markLayoutNodeDirty(bool shouldForceUpdateLayoutBounds) {}
void LayoutComponent::markLayoutStyleDirty() {}
void LayoutComponent::onDirty(ComponentDirt value) {}
bool LayoutComponent::mainAxisIsRow() { return true; }

bool LayoutComponent::mainAxisIsColumn() { return false; }
bool LayoutComponent::isStackContainer() { return false; }
void LayoutComponent::calculateLayoutInternal(float availableWidth,
                                              float availableHeight)
{}
#endif

LayoutComponent::~LayoutComponent()
{
    if (artboard() != nullptr)
    {
        artboard()->cleanLayout(this);
    }
#ifdef WITH_RIVE_TOOLS
    m_layoutData->unref();
#else
    delete m_layoutData;
#endif
}

void LayoutComponent::clipChanged()
{
    markLayoutNodeDirty();
    addDirt(ComponentDirt::Path);
}
void LayoutComponent::widthChanged() { markLayoutNodeDirty(); }
void LayoutComponent::heightChanged() { markLayoutNodeDirty(); }
void LayoutComponent::styleIdChanged() { markLayoutNodeDirty(); }
void LayoutComponent::fractionalWidthChanged() { markLayoutNodeDirty(); }
void LayoutComponent::fractionalHeightChanged() { markLayoutNodeDirty(); }

ShapePaintPath* LayoutComponent::worldPath()
{
    return m_renderPaths != nullptr ? &m_renderPaths->world : nullptr;
}
ShapePaintPath* LayoutComponent::localPath()
{
    return m_renderPaths != nullptr ? &m_renderPaths->local : nullptr;
}
ShapePaintPath* LayoutComponent::localClockwisePath()
{
    return m_renderPaths != nullptr ? &m_renderPaths->local : nullptr;
}

Component* LayoutComponent::pathBuilder() { return this; }