#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)
{
    Vec2D size = ((LayoutComponent*)node->getContext())
                     ->measureLayout(width,
                                     (LayoutMeasureMode)widthMode,
                                     height,
                                     (LayoutMeasureMode)heightMode);

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

Vec2D LayoutComponent::measureLayout(float width,
                                     LayoutMeasureMode widthMode,
                                     float height,
                                     LayoutMeasureMode 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;
        auto animationData = currentAnimationData();
        animationData->from = newLayout;
        animationData->to = newLayout;
        animationData->elapsedSeconds = 0.0f;
        propagateSize();
        markWorldTransformDirty();
        setLayoutFlag(LayoutComponentFlags::ForceUpdateLayoutBounds, false);
        return;
    }

    if (animate && animates())
    {
        auto animationData = currentAnimationData();
        if (newLayout != animationData->to ||
            hasLayoutFlag(LayoutComponentFlags::ForceUpdateLayoutBounds))
        {
            if (animationData->elapsedSeconds != 0.0f)
            {
                if (hasLayoutFlag(LayoutComponentFlags::IsSmoothingAnimation))
                {
                    // we were already smoothening.
                    m_animationDataA.copy(m_animationDataB);
                }
                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_animationDataA.to = m_layout = 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:
            return m_inheritedInterpolator != nullptr ? m_inheritedInterpolator
                                                      : 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_inheritedInterpolation;
        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_inheritedInterpolationTime;
        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 (inheritedInterpolation != m_inheritedInterpolation ||
        inheritedInterpolator != m_inheritedInterpolator ||
        inheritedInterpolationTime != m_inheritedInterpolationTime)
    {
        m_inheritedInterpolation = inheritedInterpolation;
        m_inheritedInterpolator = inheritedInterpolator;
        m_inheritedInterpolationTime = inheritedInterpolationTime;
        return true;
    }
    return false;
}

void LayoutComponent::clearInheritedInterpolation()
{
    m_inheritedInterpolation = LayoutStyleInterpolation::hold;
    m_inheritedInterpolator = nullptr;
    m_inheritedInterpolationTime = 0;
}

LayoutAnimationData* LayoutComponent::currentAnimationData()
{
    return hasLayoutFlag(LayoutComponentFlags::IsSmoothingAnimation)
               ? &m_animationDataB
               : &m_animationDataA;
}

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();
    if (!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_animationDataA.elapsedSeconds /
                                      interpolationTime()
                                : 1.0f);

        if (interpolation() != LayoutStyleInterpolation::linear &&
            interpolator() != nullptr)
        {
            f = interpolator()->transform(f);
        }
        m_animationDataB.from = m_animationDataA.interpolate(f);
        if (f == 1.0f)
        {
            m_animationDataA.copy(m_animationDataB);
            setLayoutFlag(LayoutComponentFlags::IsSmoothingAnimation, false);
        }
        else
        {
            m_animationDataA.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_animationDataA.copy(m_animationDataB);
            m_animationDataA.elapsedSeconds = m_animationDataB.elapsedSeconds =
                0.0f;
        }
        else
        {
            m_animationDataA.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())
    {
        m_layout = currentAnimationData()->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; }