#include "rive/text/text.hpp"
#include "rive/layout/layout_participant.hpp"
#include "rive/importers/import_stack.hpp"
using namespace rive;
#ifdef WITH_RIVE_TEXT
#include "rive/text_engine.hpp"
#include "rive/component_dirt.hpp"
#include "rive/math/rectangles_to_contour.hpp"
#include "rive/math/transform_components.hpp"
#include "rive/text/text_style_background.hpp"
#include "rive/text/text_style_paint.hpp"
#include "rive/text/text_value_run.hpp"
#include "rive/text/text_modifier_group.hpp"
#include "rive/text/text_selection_controller.hpp"
#include "rive/shapes/paint/shape_paint.hpp"
#include "rive/shapes/paint/color.hpp"
#include "rive/shapes/paint/blend_mode.hpp"
#include "rive/shapes/paint/image_sampler.hpp"
#include "rive/viewmodel/viewmodel_instance_string.hpp"
#include "rive/viewmodel/viewmodel_instance_artboard.hpp"
#include "rive/text/text_style_global.hpp"
#include "rive/text/text_style_instance.hpp"
#include "rive/text/text_style_on_demand.hpp"
#include "rive/artboard.hpp"
#include "rive/bindable_artboard.hpp"
#include "rive/file.hpp"
#include "rive/factory.hpp"
#include "rive/clip_result.hpp"
#include "rive/generated/core_registry.hpp"
#include <algorithm>
#include <cstring>
#include <limits>
#include <unordered_set>

TextValueRunProperty::TextValueRunProperty(
    Core* textValueRun,
    TextValueRunListener* textValueRunListener,
    ViewModelInstanceValue* instanceValue,
    uint16_t propertyKey,
    SymbolType symbolType)
    : PropertySymbolDependentSingle(
          textValueRun,
          textValueRunListener,
          instanceValue,
          propertyKey)
    , m_symbolType(symbolType)
{}

void TextValueRunProperty::writeValue()
{
  switch (m_symbolType)
  {
    case SymbolType::textContent:
      if (m_instanceValue->is<ViewModelInstanceString>())
      {
        CoreRegistry::setString(
            m_coreObject,
            m_propertyKey,
            m_instanceValue->as<ViewModelInstanceString>()->propertyValue());
      }
      break;
    case SymbolType::textStyle:
    case SymbolType::globalTextStyle:
      // Both style symbols resolve together, so whichever fires the
      // result is the same.
      static_cast<TextValueRunListener*>(m_coreObjectListener)->resolveStyle();
      break;
    default:
      break;
  }
}

TextValueRunListener::TextValueRunListener(
    TextValueRun* textValueRun,
    rcp<ViewModelInstance> instance,
    Text* text)
    : CoreObjectListener(textValueRun, instance)
    , m_text(text)
{
  createProperties();
}

void TextValueRunListener::markDirty() { m_text->markShapeDirty(); }

void TextValueRunListener::resolveStyle()
{
  auto run = textValueRun();
  if (run != nullptr)
  {
    // Never through styleId: list runs aren't in an artboard.
    run->style(m_text->resolveListRunStyle(m_instance.get()));
  }
}

void TextValueRunListener::createProperties()
{
  CoreObjectListener::createProperties();
  createPropertyListener(SymbolType::textStyle);
  createPropertyListener(SymbolType::globalTextStyle);
  createPropertyListener(SymbolType::textContent);
}

TextValueRunProperty* TextValueRunListener::createSinglePropertyListener(
    SymbolType symbolType)
{
  uint16_t propertyKey = 0;
  bool expectsString = true;
  switch (symbolType)
  {
    case SymbolType::textStyle:
      propertyKey = TextValueRunBase::styleIdPropertyKey;
      break;
    case SymbolType::globalTextStyle:
      propertyKey = TextValueRunBase::styleIdPropertyKey;
      expectsString = false;
      break;
    case SymbolType::textContent:
      propertyKey = TextValueRunBase::textPropertyKey;
      break;
    default:
      break;
  }
  auto prop = m_instance->propertyValue(symbolType);
  if (prop != nullptr &&
      (expectsString ? prop->is<ViewModelInstanceString>()
                     : prop->is<ViewModelInstanceArtboard>()))
  {
    auto vpl = new TextValueRunProperty(
        m_core,
        this,
        prop,
        propertyKey,
        symbolType);
    return vpl;
  }
  return nullptr;
}

void TextValueRunListener::createPropertyListener(SymbolType symbolType)
{
  TextValueRunProperty* listener = nullptr;
  switch (symbolType)
  {
    case SymbolType::textStyle:
    case SymbolType::globalTextStyle:
    case SymbolType::textContent:
      listener = createSinglePropertyListener(symbolType);
      break;
    default:
      break;
  }
  if (listener != nullptr)
  {
    listener->writeValue();
    m_properties.push_back(listener);
  }
}

Text::~Text()
{
  if (m_selectionController != nullptr)
  {
    m_selectionController->remove(this);
  }
  // Listeners own their runs, which point into the on-demand styles: drop
  // the runs first.
  for (auto& textValueRun : m_valueRunListeners)
  {
    delete textValueRun;
  }
  m_valueRunListeners.clear();
  m_onDemandStyles.clear();
}

Vec2D Text::measureLayout(
    float width,
    LayoutMeasureMode widthMode,
    float height,
    LayoutMeasureMode heightMode)
{
  return measure(Vec2D(
      widthMode == LayoutMeasureMode::undefined
          ? std::numeric_limits<float>::max()
          : width,
      heightMode == LayoutMeasureMode::undefined
          ? std::numeric_limits<float>::max()
          : height));
}

void Text::controlSize(
    Vec2D size,
    LayoutScaleType widthScaleType,
    LayoutScaleType heightScaleType,
    LayoutDirection direction)
{
  if (m_layoutWidth != size.x || m_layoutHeight != size.y ||
      m_layoutWidthScaleType != (uint8_t)widthScaleType ||
      m_layoutHeightScaleType != (uint8_t)heightScaleType ||
      m_layoutDirection != direction)
  {
    m_layoutWidth = size.x;
    m_layoutHeight = size.y;
    m_layoutWidthScaleType = (uint8_t)widthScaleType;
    m_layoutHeightScaleType = (uint8_t)heightScaleType;
    m_layoutDirection = direction;
    markShapeDirty(false);
  }
}

TextSizing Text::effectiveSizing() const
{
#ifdef WITH_RIVE_LAYOUT
  // Layout-controlled text (a participant, or the active child of a
  // participating Solo) carries independent per-axis scale types; the single
  // TextSizing enum can't express e.g. hug-width + fixed-height, so map each
  // combination to the closest box behavior. m_layoutWidth/Height already
  // hold the resolved slot sizes, so a hug axis reads as its content size
  // under `fixed`.
  //
  // Read the scale types off the PARTICIPANT rather than off the copy
  // controlSize leaves behind. Only the resolved slot has to wait for the
  // solve; the scale types are authored, and controlSize hands us the
  // participant's own values verbatim. Taking the copy meant the first
  // measure pass -- which runs during the solve, before controlSize -- saw
  // them unset and fell back to sizing(), so a fitFontSize text was fitted
  // to the width the layout was offering and only settled on the next
  // advance.
  if (auto* participant = layoutParticipant())
  {
    const auto widthScaleType = (LayoutScaleType)
                                    participant->layoutWidthScaleType();
    const auto heightScaleType = (LayoutScaleType)
                                     participant->layoutHeightScaleType();
    bool wBox = widthScaleType == LayoutScaleType::fixed ||
                widthScaleType == LayoutScaleType::fill;
    bool hBox = heightScaleType == LayoutScaleType::fixed ||
                heightScaleType == LayoutScaleType::fill;
    if (!wBox && !hBox)
    {
      return sizing();
    }
    return wBox && !hBox ? TextSizing::autoHeight : TextSizing::fixed;
  }
#endif
  if (m_layoutWidthScaleType == std::numeric_limits<uint8_t>::max() ||
      m_layoutWidthScaleType == (uint8_t)LayoutScaleType::hug ||
      m_layoutHeightScaleType == (uint8_t)LayoutScaleType::hug)
  {
    return sizing();
  }
  return TextSizing::fixed;
}

void Text::clearRenderStyles()
{
  for (TextStylePaint* style : m_renderStyles)
  {
    style->rewindPath();
  }
  m_renderStyles.clear();
  m_drawCommands.clear();
  for (auto& entry : m_sharedGeometry)
  {
    entry.second->rewind();
  }
  for (TextStyleBackground* background : m_globalBackgrounds)
  {
    background->resetPath();
  }
  m_globalBackgrounds.clear();

  // Backgrounds reset off the child list; a style whose glyphs are all
  // emoji never enters m_renderStyles.
  buildTextStylePaints();
  for (TextStylePaint* style : m_textStylePaints)
  {
    if (style->background() != nullptr)
    {
      style->background()->resetPath();
    }
  }

  for (TextValueRun* textValueRun : m_allRuns)
  {
    textValueRun->resetHitTest();
  }
}

// Vertical trim: the ascent above the first line's cap- or x-height and the
// descent below the last line's baseline (or natural descent) that should be
// removed from the box. Glyph layout is unchanged. Shared by computeBoundsInfo
// (rendering) and measure (layout), so it operates on supplied lines/shape.
static void computeVerticalTrim(
    const SimpleArray<SimpleArray<GlyphLine>>& lines,
    const SimpleArray<Paragraph>& shape,
    TextTrimTop trimTop,
    TextTrimBottom trimBottom,
    float& topTrim,
    float& bottomTrim)
{
  topTrim = 0.0f;
  bottomTrim = 0.0f;
  if (lines.empty() ||
      (trimTop == TextTrimTop::none && trimBottom == TextTrimBottom::none))
  {
    return;
  }

  if (trimTop != TextTrimTop::none && !lines.front().empty())
  {
    const GlyphLine& firstLine = lines.front().front();
    const Paragraph& firstParagraph = shape[0];
    // Largest top edge across the runs on the first line so that no glyph
    // is clipped. capHeight/xHeight are stored negative (up is -Y).
    float edgePx = 0.0f;
    for (uint32_t i = firstLine.startRunIndex; i <= firstLine.endRunIndex; ++i)
    {
      const Font::LineMetrics& metrics = firstParagraph.runs[i]
                                             .font->lineMetrics();
      float edge = trimTop == TextTrimTop::cap ? metrics.capHeight
                                               : metrics.xHeight;
      edgePx = std::max(edgePx, -edge * firstParagraph.runs[i].size);
    }
    topTrim = std::max(0.0f, (firstLine.baseline - edgePx) - firstLine.top);
  }

  // Bottom trim uses the last non-empty paragraph's last line.
  if (trimBottom != TextTrimBottom::none)
  {
    for (size_t p = lines.size(); p-- > 0;)
    {
      const SimpleArray<GlyphLine>& paragraphLines = lines[p];
      if (paragraphLines.empty())
      {
        continue;
      }
      const GlyphLine& lastLine = paragraphLines.back();
      float descentBand = lastLine.bottom - lastLine.baseline;
      if (trimBottom == TextTrimBottom::alphabetic)
      {
        // Box bottom at the baseline: remove the whole descent.
        bottomTrim = std::max(0.0f, descentBand);
      }
      else
      {
        // Box bottom at the natural descent: keep the descenders,
        // remove only any extra leading below them.
        const Paragraph& lastParagraph = shape[p];
        float descentPx = 0.0f;
        for (uint32_t i = lastLine.startRunIndex; i <= lastLine.endRunIndex;
             ++i)
        {
          const GlyphRun& run = lastParagraph.runs[i];
          descentPx = std::max(
              descentPx,
              run.font->lineMetrics().descent * run.size);
        }
        bottomTrim = std::max(0.0f, descentBand - descentPx);
      }
      break;
    }
  }
}

TextBoundsInfo Text::computeBoundsInfo()
{
  const float paragraphSpace = fitParagraphSpacing();

  // Build up ordered runs as we go.
  int paragraphIndex = 0;
  float y = 0.0f;
  float minY = 0.0f;
  float maxWidth = 0.0f;
  float ellipsedHeight = 0;
  if (textOrigin() == TextOrigin::baseline && !m_lines.empty() &&
      !m_lines[0].empty())
  {
    y -= m_lines[0][0].baseline;
    minY = y;
  }

  int ellipsisLine = -1;
  bool isEllipsisLineLast = false;
  // Find the line to put the ellipsis on (line before the one that
  // overflows).
  bool wantEllipsis = overflow() == TextOverflow::ellipsis && overflowAsFixed();

  int lastLineIndex = -1;
  for (const SimpleArray<GlyphLine>& paragraphLines : m_lines)
  {
    const Paragraph& paragraph = m_shape[paragraphIndex++];
    for (const GlyphLine& line : paragraphLines)
    {
      const GlyphRun& endRun = paragraph.runs[line.endRunIndex];
      const GlyphRun& startRun = paragraph.runs[line.startRunIndex];
      float width = endRun.xpos[line.endGlyphIndex] -
                    startRun.xpos[line.startGlyphIndex];
      if (width > maxWidth)
      {
        maxWidth = width;
      }
      lastLineIndex++;
      if (wantEllipsis && y + line.bottom <= effectiveHeight())
      {
        ellipsedHeight = y + line.bottom;
        ellipsisLine++;
      }
    }

    if (!paragraphLines.empty())
    {
      y += paragraphLines.back().bottom;
    }
    y += paragraphSpace;
  }
  if (wantEllipsis && ellipsisLine == -1)
  {
    // Nothing fits, just show the first line and ellipse it.
    ellipsisLine = 0;
  }
  auto totalHeight = ellipsisLine > 0 ? ellipsedHeight : y;
  isEllipsisLineLast = lastLineIndex == ellipsisLine;

  // Vertical trim: shrink the box to the chosen cap/x-height + baseline band.
  // Glyph layout is unchanged; fixed sizing keeps its authored box.
  float topTrim = 0.0f;
  float bottomTrim = 0.0f;
  if (effectiveSizing() != TextSizing::fixed)
  {
    computeVerticalTrim(
        m_lines,
        m_shape,
        verticalTrimTop(),
        verticalTrimBottom(),
        topTrim,
        bottomTrim);
  }

  return {
      minY,
      maxWidth,
      totalHeight,
      ellipsisLine,
      isEllipsisLineLast,
      topTrim,
      bottomTrim,
  };
}

float Text::fitFontScale()
{
  const TextSizing sizing = effectiveSizing();
  // Without a fixed dimension to fit into there is nothing to search:
  // autoWidth grows in both directions, so we keep the authored size.
  if (sizing == TextSizing::autoWidth && !overflowAsFixed())
  {
    return 1.0f;
  }
  return fitFontScale(
      effectiveWidth(),
      overflowAsFixed() ? effectiveHeight()
                        : std::numeric_limits<float>::max());
}

float Text::fitFontScale(float boxWidth, float boxHeight)
{
  // The box we are fitting into is the *trimmed* one: computeBoundsInfo and
  // measure both take the trim band off the content height before the box is
  // sized, so boxHeight already excludes it (it is the height the layout
  // handed back, or the offer measure is fitting into). Comparing the raw
  // content height against it would charge the trim band twice and shrink
  // the font by it, leaving exactly the dead space the trim removed. Gated
  // like computeBoundsInfo: a fixed box keeps its authored, untrimmed size.
  const bool boxIsTrimmed = effectiveSizing() != TextSizing::fixed;

  // Largest authored font size across runs is our maximum; we search integer
  // sizes in [1, maxSize]. Scaling all runs by a single multiplier preserves
  // their relative proportions while stepping the largest run by integers.
  float maxSize = 0.0f;
  for (TextValueRun* valueRun : m_allRuns)
  {
    TextStylePaint* style = valueRun->style();
    if (style != nullptr && style->font() != nullptr &&
        !valueRun->text().empty())
    {
      // No scale turns inf finite (inf * 0 is NaN). std::max drops NaN.
      if (std::isinf(style->fontSize()))
      {
        return 1.0f;
      }
      maxSize = std::max(maxSize, style->fontSize());
    }
  }

  if (maxSize <= 1.0f)
  {
    return 1.0f;
  }

  StyledText styledText;

  // Shapes and lays out the text at the given integer top size and reports
  // whether it fits the bounds. Text dimensions grow monotonically with size,
  // so this predicate is monotonic and binary-searchable.
  auto fits = [&](int topSize) -> bool {
    float scale = (float)topSize / maxSize;
    if (!makeStyled(styledText, true, scale))
    {
      // Nothing to lay out: trivially fits.
      return true;
    }
    const auto& runs = styledText.runs();
    auto shape = runs[0].font->shapeText(styledText.unichars(), runs);
    auto lines = BreakLines(shape, boxWidth, align(), wrap(), wordBreak());

    float maxWidth = 0.0f;
    float y = 0.0f;
    size_t paragraphIndex = 0;
    for (const SimpleArray<GlyphLine>& paragraphLines : lines)
    {
      const Paragraph& paragraph = shape[paragraphIndex++];
      for (const GlyphLine& line : paragraphLines)
      {
        const GlyphRun& endRun = paragraph.runs[line.endRunIndex];
        const GlyphRun& startRun = paragraph.runs[line.startRunIndex];
        float width = endRun.xpos[line.endGlyphIndex] -
                      startRun.xpos[line.startGlyphIndex];
        maxWidth = std::max(maxWidth, width);
      }
      if (!paragraphLines.empty())
      {
        y += paragraphLines.back().bottom;
      }
      y += paragraphSpacing() * scale;
    }

    float topTrim = 0.0f;
    float bottomTrim = 0.0f;
    if (boxIsTrimmed)
    {
      computeVerticalTrim(
          lines,
          shape,
          verticalTrimTop(),
          verticalTrimBottom(),
          topTrim,
          bottomTrim);
    }

    bool widthFits = maxWidth <= boxWidth;
    bool heightFits = y - topTrim - bottomTrim <= boxHeight;
    return widthFits && heightFits;
  };

  // Above 2^24 floats skip integers, and hi + 1 must not overflow int.
  constexpr float kMaxSearchSize = (float)(1 << 24);
  // Binary search for the largest integer top size in [1, floor(maxSize)]
  // that fits. If nothing fits we fall back to the minimum size (1).
  int lo = 1;
  int hi = (int)std::min(maxSize, kMaxSearchSize);
  // Most texts fit at their authored size, which the search below only
  // reaches after shaping every halving on the way up. The predicate is
  // monotonic, so checking the top first returns the same size.
  if (fits(hi))
  {
    return (float)hi / maxSize;
  }
  hi--;
  int best = 1;
  while (lo <= hi)
  {
    int mid = lo + (hi - lo) / 2;
    if (fits(mid))
    {
      best = mid;
      lo = mid + 1;
    }
    else
    {
      hi = mid - 1;
    }
  }
  return (float)best / maxSize;
}

LineIter Text::shouldDrawLine(
    float curY,
    float totalHeight,
    const GlyphLine& line)
{
  switch (overflow())
  {
    case TextOverflow::hidden:
      if (overflowAsFixed())
      {
        switch (verticalAlign())
        {
          case VerticalTextAlign::top:
            if (curY + line.bottom > effectiveHeight())
            {
              return LineIter::yOutOfBounds;
            }
            break;
          case VerticalTextAlign::middle:
            if (curY + line.top < totalHeight / 2 - effectiveHeight() / 2)
            {
              return LineIter::skipThisLine;
            }
            if (curY + line.bottom > totalHeight / 2 + effectiveHeight() / 2)
            {
              return LineIter::yOutOfBounds;
            }
            break;
          case VerticalTextAlign::bottom:
            if (curY + line.top < totalHeight - effectiveHeight())
            {
              return LineIter::skipThisLine;
            }
            break;
        }
      }
      break;
    case TextOverflow::clipped:
      if (overflowAsFixed())
      {
        switch (verticalAlign())
        {
          case VerticalTextAlign::top:
            if (curY + line.top > effectiveHeight())
            {
              return LineIter::yOutOfBounds;
            }
            break;
          case VerticalTextAlign::middle:
            if (curY + line.bottom < totalHeight / 2 - effectiveHeight() / 2)
            {
              return LineIter::skipThisLine;
            }
            if (curY + line.top > totalHeight / 2 + effectiveHeight() / 2)
            {
              return LineIter::yOutOfBounds;
            }
            break;
          case VerticalTextAlign::bottom:
            if (curY + line.bottom < totalHeight - effectiveHeight())
            {
              return LineIter::skipThisLine;
            }
            break;
        }
      }
      break;
    default:
      break;
  }
  return LineIter::drawLine;
}

void Text::buildRenderStyles()
{
  // Step 1: reset stuff. Every build lays the lines out again, so a
  // paint-only rebuild must not append to the last build's lines.
  clearRenderStyles();
  m_orderedLines.clear();

  if (m_shape.empty())
  {
    m_bounds = AABB(0.0f, 0.0f, 0.0f, 0.0f);
    return;
  }

  // Step 2: compute ellipsis information
  TextBoundsInfo info = computeBoundsInfo();
  float minY = info.minY;
  float maxWidth = info.maxWidth;
  float totalHeight = info.totalHeight;
  int ellipsisLine = info.ellipsisLine;
  bool isEllipsisLineLast = info.isEllipsisLineLast;
  float topTrim = info.topTrim;
  float bottomTrim = info.bottomTrim;

  // Step 3: update modifiers
  bool hasModifiers = haveModifiers();
  if (hasModifiers)
  {
    uint32_t textSize = (uint32_t)m_styledText.unichars().size();
    for (TextModifierGroup* modifierGroup : m_modifierGroups)
    {
      modifierGroup->computeCoverage(textSize);
      modifierGroup->resetTextFollowPath();
    }
  }

  // Step 4: update bounds. A layout-controlled axis uses the layout's size
  // so the text box always matches the layout.
  const float paragraphSpace = fitParagraphSpacing();
  const float boxWidth = layoutBoxWidth();
  const float boxHeight = layoutBoxHeight();
  const float autoSizeMaxY = std::isnan(boxHeight)
                                 ? std::max(
                                       minY,
                                       totalHeight - paragraphSpace - topTrim -
                                           bottomTrim)
                                 : minY + boxHeight;
  switch (effectiveSizing())
  {
    case TextSizing::autoWidth:
      m_bounds = AABB(
          0.0f,
          minY,
          std::isnan(boxWidth) ? maxWidth : boxWidth,
          autoSizeMaxY);
      break;
    case TextSizing::autoHeight:
      m_bounds = AABB(0.0f, minY, effectiveWidth(), autoSizeMaxY);
      break;
    case TextSizing::fixed:
      m_bounds = AABB(0.0f, minY, effectiveWidth(), minY + effectiveHeight());
      break;
  }

  auto verticalAlignOffset = 0.0f;
  switch (verticalAlign())
  {
    case VerticalTextAlign::middle:
      verticalAlignOffset = (totalHeight - m_bounds.height()) / 2;
      break;
    case VerticalTextAlign::bottom:
      verticalAlignOffset = totalHeight - m_bounds.height();
      break;
    default:
      break;
  }

  // Step 5: Update clip information (if we want it)
  if (overflow() == TextOverflow::clipped)
  {
    m_clipRect.rewind();

    AABB bounds = localBounds();

    float minX = bounds.minX + bounds.width() * originX();
    float minY = bounds.minY + bounds.height() * originY() +
                 verticalAlignOffset;
    m_clipRect.addRect(
        AABB(minX, minY, minX + bounds.width(), minY + bounds.height()));
  }

  // Step 6: add the glyphs to render paths. Shift content up by topTrim so
  // the first line's cap-height line aligns with the (trimmed) box top.
  float curY = minY - topTrim;
  int lineIndex = 0;
  int paragraphIndex = 0;
  float minX = std::numeric_limits<float>::max();

  for (const SimpleArray<GlyphLine>& paragraphLines : m_lines)
  {
    const Paragraph& paragraph = m_shape[paragraphIndex++];
    int lineIndexInParagraph = 0;
    for (const GlyphLine& line : paragraphLines)
    {
      LineIter lineIter = shouldDrawLine(curY, totalHeight, line);
      if (lineIter == LineIter::yOutOfBounds)
      {
        goto skipLines;
      }
      else if (lineIter == LineIter::skipThisLine)
      {
        lineIndexInParagraph++;
        lineIndex++;
        continue;
      }

      float renderY = curY + line.baseline;
      // We need to compute this line's ordered runs.
      m_orderedLines.emplace_back(OrderedLine(
          paragraph,
          line,
          effectiveWidth(),
          align(),
          ellipsisLine == lineIndex,
          isEllipsisLineLast,
          &m_ellipsisRun,
          renderY));

      float curX = m_orderedLines.back().startX();
      minX = std::min(curX, minX);
      for (auto glyphItr : m_orderedLines.back())
      {
        const GlyphRun* run = std::get<0>(glyphItr);
        size_t glyphIndex = std::get<1>(glyphItr);

        const Font* font = run->font.get();
        const Vec2D& offset = run->offsets[glyphIndex];

        GlyphID glyphId = run->glyphs[glyphIndex];
        float advance = run->advances[glyphIndex];

        // Step 6.1: translate to the glyph's origin and scale.
        Vec2D curPos(curX, renderY);
        float centerX = advance / 2.0f;
        TransformComponents tc;
        tc.scaleX(run->size);
        tc.scaleY(run->size);
        tc.x(-centerX);
        Mat2D pathTransform = Mat2D::compose(tc);

        // Step 6.2: apply modifiers on a font-sized glyph
        float opacity = 1.0f;
        if (hasModifiers)
        {
          uint32_t textIndex = run->textIndices[glyphIndex];
          uint32_t glyphCount = m_glyphLookup.count(textIndex);

          for (TextModifierGroup* modifierGroup : m_modifierGroups)
          {
            float coverage = modifierGroup->glyphCoverage(
                textIndex,
                glyphCount);
            TransformGlyphArg arg = {
                curPos,
                centerX,
                lineIndexInParagraph,
                paragraphLines,
            };
            modifierGroup->transform(coverage, pathTransform, arg);
            if (modifierGroup->modifiesOpacity())
            {
              opacity = modifierGroup->computeOpacity(opacity, coverage);
            }
          }
        }

        // Step 6.3: translate back to center with offset
        pathTransform = Mat2D::fromTranslate(
                            curPos.x + centerX + offset.x,
                            curPos.y + offset.y) *
                        pathTransform;

        assert(run->styleId < m_allRuns.size());
        TextValueRun* textValueRun = m_allRuns[run->styleId];
        TextStylePaint* style = textValueRun->style();
        assert(style != nullptr);

        // Check for color glyph (emoji) -- draw individually
        // with per-layer colors instead of accumulating.
        if (font->isColorGlyph(glyphId))
        {
          TextDrawCommand cmd;
          cmd.type = TextDrawCommand::kColorGlyph;
          cmd.colorGlyph = {
              run->font,
              glyphId,
              pathTransform,
              style->foregroundColor(),
              opacity};
          m_drawCommands.push_back(std::move(cmd));
        }
        else
        {
          // Placed as it's added: the font's own outline, not a copy.
          const RawPath& path = font->glyphPath(glyphId);

          if (style->isShared())
          {
            // A paint other Texts draw too: keep this Text's
            // glyphs here, and leave the paint untouched.
            TextStyleGeometry& geometry = sharedGeometry(style);
            if (geometry.addPath(path, opacity, &pathTransform))
            {
              TextDrawCommand cmd;
              cmd.type = TextDrawCommand::kStylePath;
              cmd.style = style;
              cmd.geometry = &geometry;
              m_drawCommands.push_back(std::move(cmd));
            }
          }
          else if (style->addPath(path, opacity, &pathTransform))
          {
            // This was the first path added to the style, so
            // let's mark it in our draw list.
            m_renderStyles.push_back(style);
            style->propagateOpacity(renderOpacity());

            TextDrawCommand cmd;
            cmd.type = TextDrawCommand::kStylePath;
            cmd.style = style;
            m_drawCommands.push_back(std::move(cmd));
          }
        }

        // Bounds of the glyph
        if (textValueRun->isHitTarget() || style->background() != nullptr)
        {
          AABB glyphBounds(
              curX,
              curY + line.top,
              curX + advance,
              curY + line.bottom);
          if (textValueRun->isHitTarget())
          {
            textValueRun->addHitRect(glyphBounds);
          }
          if (style->background() != nullptr)
          {
            TextStyleBackground* background = style->background();
            // A global style's background isn't one of this
            // Text's children: remember it to reset, update and
            // draw it.
            if (style->parent() != this &&
                std::find(
                    m_globalBackgrounds.begin(),
                    m_globalBackgrounds.end(),
                    background) == m_globalBackgrounds.end())
            {
              m_globalBackgrounds.push_back(background);
            }
            background->addRect(glyphBounds);
          }
        }
        curX += advance;
      }
      if (lineIndex == ellipsisLine)
      {
        goto skipLines;
      }
      lineIndexInParagraph++;
      lineIndex++;
    }
    if (!paragraphLines.empty())
    {
      curY += paragraphLines.back().bottom;
    }
    curY += fitParagraphSpacing();
  }
skipLines:
  // Step 7: consider fit mode, and update local transform
  auto scale = 1.0f;
  auto xOffset = -m_bounds.width() * originX();
  auto yOffset = -m_bounds.height() * originY();
  if (overflow() == TextOverflow::fit)
  {
    auto xScale = ((effectiveSizing() != TextSizing::autoWidth ||
                    overflowAsFixed()) &&
                   maxWidth > m_bounds.width())
                      ? m_bounds.width() / maxWidth
                      : 1;
    auto baseline = fitFromBaseline() ? m_lines[0][0].baseline : 0;
    auto yScale = (overflowAsFixed() && totalHeight > m_bounds.height())
                      ? (m_bounds.height() - baseline) /
                            (totalHeight - baseline)
                      : 1;
    if (xScale != 1 || yScale != 1)
    {
      scale = std::max(0.0f, xScale > yScale ? yScale : xScale);
      yOffset += baseline * (1 - scale);
      switch (align())
      {
        case TextAlign::center:
          xOffset += (m_bounds.width() - maxWidth * scale) / 2 - minX * scale;
          break;
        case TextAlign::right:
          xOffset += m_bounds.width() - maxWidth * scale - minX * scale;
          break;
        default:
          break;
      }
    }
  }
  if (verticalAlign() != VerticalTextAlign::top)
  {
    if (overflowAsFixed())
    {
      yOffset = -m_bounds.height() * originY();
      if (verticalAlign() == VerticalTextAlign::middle)
      {
        yOffset += (m_bounds.height() - totalHeight * scale) / 2;
      }
      else if (verticalAlign() == VerticalTextAlign::bottom)
      {
        yOffset += m_bounds.height() - totalHeight * scale;
      }
    }
  }
  m_transform = Mat2D::fromScaleAndTranslation(scale, scale, xOffset, yOffset);
#ifdef WITH_RIVE_LAYOUT
  // The layout sizes this text by measuring it, and a change to anything it
  // measures marks the layout dirty first (markShapeDirty), so the solve
  // that just ran already saw this shape. Re-marking it unconditionally ran
  // a second full solve after every text change, and one after every paint
  // change too, since a recolor rebuilds the render styles. It is still owed
  // when the shape and the measurement disagree: a modifier reshaped the
  // text without telling the layout, or the solve handed us scale types or
  // a direction that change what measure() reports. A solve that sizes us
  // from the style alone (a fixed or filled slot) never calls measure(), so
  // the key can go stale with nothing owed: ask once, and a solve that
  // measures us records a fresh key, while one that doesn't leaves 0, which
  // stops us asking again until the next measure.
  if (m_measuredKey != 0 && m_shapedKey != m_measuredKey)
  {
    m_measuredKey = 0;
    markLayoutNodeDirty();
  }
#endif

  // Step 8: cleanup
  for (TextValueRun* textValueRun : m_allRuns)
  {
    if (textValueRun->isHitTarget())
    {
      textValueRun->computeHitContours();
    }
  }
  for (TextStylePaint* style : m_textStylePaints)
  {
    TextStyleBackground* background = style->background();
    if (background != nullptr)
    {
      background->updatePath();
      background->propagateOpacity(renderOpacity());
    }
  }
  for (TextStyleBackground* background : m_globalBackgrounds)
  {
    background->updatePath();
    background->propagateOpacity(renderOpacity());
  }
  // Drop the geometry of shared paints this build no longer drew.
  m_sharedGeometry.erase(
      std::remove_if(
          m_sharedGeometry.begin(),
          m_sharedGeometry.end(),
          [](const std::pair<
              TextStylePaint*,
              std::unique_ptr<TextStyleGeometry>>& entry) {
            return !entry.second->hasContents();
          }),
      m_sharedGeometry.end());
}

TextStyleGeometry& Text::sharedGeometry(TextStylePaint* paint)
{
  for (auto& entry : m_sharedGeometry)
  {
    if (entry.first == paint)
    {
      return *entry.second;
    }
  }
  m_sharedGeometry.emplace_back(paint, std::make_unique<TextStyleGeometry>());
  return *m_sharedGeometry.back().second;
}

const TextStylePaint* Text::styleFromShaperId(uint16_t id) const
{
  // Shaper ids index every run, list-driven ones included.
  assert(id < m_allRuns.size());
  return m_allRuns[id]->style();
}

void Text::draw(Renderer* renderer)
{
  if (needsSaveOperation())
  {
    renderer->save();
  }
  // For now we need to check both empty() and hasRenderPath() in
  // ShapePaintPath because the raw path gets cleared when the render path
  // is created.
  if (overflow() == TextOverflow::clipped &&
      (!m_clipPath.empty() || m_clipPath.hasRenderPath()))
  {
    renderer->clipPath(m_clipPath.renderPath(this));
  }
  auto worldTransform = shapeWorldTransform();
  // Backgrounds first so they sit behind every glyph, in style child order.
  for (TextStylePaint* style : m_textStylePaints)
  {
    TextStyleBackground* background = style->background();
    if (background != nullptr)
    {
      background->draw(renderer, worldTransform);
    }
  }
  for (TextStyleBackground* background : m_globalBackgrounds)
  {
    background->draw(renderer, worldTransform);
  }
  if (m_selectionController != nullptr)
  {
    m_selectionController->draw(this, renderer);
  }
  for (auto& cmd : m_drawCommands)
  {
    if (cmd.type == TextDrawCommand::kStylePath)
    {
      if (cmd.geometry != nullptr)
      {
        cmd.style->drawGeometry(
            renderer,
            worldTransform,
            *cmd.geometry,
            renderOpacity());
      }
      else
      {
        cmd.style->draw(renderer, worldTransform);
      }
    }
    else
    {
      drawColorGlyph(renderer, cmd.colorGlyph, worldTransform);
    }
  }
  if (needsSaveOperation())
  {
    renderer->restore();
  }
}

void rive::drawColorGlyphLayer(
    Renderer* renderer,
    Factory* factory,
    Font::ColorGlyphLayer& layer,
    float opacity)
{
  using PaintType = Font::ColorGlyphPaintType;
  auto paint = factory->makeRenderPaint();
  paint->style(RenderPaintStyle::fill);
  Mat2D toUnitCircle;
  bool isLinear = layer.paintType == PaintType::linearGradient;
  bool isRadial = layer.paintType == PaintType::radialGradient &&
                  layer.radialTransform.invert(&toUnitCircle);
  if (layer.stops.size() < 2 || (!isLinear && !isRadial))
  {
    ColorInt color = layer.paintType == PaintType::solid || layer.stops.empty()
                         ? layer.color
                         : layer.stops.front().color;
    paint->color(colorModulateOpacity(color, opacity));
    renderer->drawPath(
        factory->makeRenderPath(layer.path, FillRule::nonZero).get(),
        paint.get());
    return;
  }

  std::vector<ColorInt> colors;
  std::vector<float> stops;
  colors.reserve(layer.stops.size());
  stops.reserve(layer.stops.size());
  for (const auto& stop : layer.stops)
  {
    colors.push_back(colorModulateOpacity(stop.color, opacity));
    stops.push_back(stop.offset);
  }
  if (isLinear)
  {
    paint->shader(factory->makeLinearGradient(
        layer.x0,
        layer.y0,
        layer.x1,
        layer.y1,
        colors.data(),
        stops.data(),
        colors.size()));
    renderer->drawPath(
        factory->makeRenderPath(layer.path, FillRule::nonZero).get(),
        paint.get());
    return;
  }

  // Radial shaders are circles, so draw in the gradient's own space.
  paint->shader(factory->makeRadialGradient(
      0,
      0,
      1,
      colors.data(),
      stops.data(),
      colors.size()));
  layer.path.transformInPlace(toUnitCircle);
  renderer->save();
  renderer->transform(layer.radialTransform);
  renderer->drawPath(
      factory->makeRenderPath(layer.path, FillRule::nonZero).get(),
      paint.get());
  renderer->restore();
}

void Text::drawColorGlyph(
    Renderer* renderer,
    const TextDrawCommand::ColorGlyphInfo& info,
    const Mat2D& worldTransform)
{
  std::vector<Font::ColorGlyphLayer> layers;
  size_t count = info.font->getColorLayers(
      info.glyphId,
      layers,
      info.foregroundColor);
  if (count == 0)
  {
    return;
  }

  Factory* factory = artboard()->factory();
  renderer->save();
  renderer->transform(worldTransform * info.transform);

  for (auto& layer : layers)
  {
    if (layer.paintType == Font::ColorGlyphPaintType::image)
    {
      // Decode and draw bitmap emoji (SBIX/CBDT).
      ColorGlyphCacheKey cacheKey{info.font.get(), info.glyphId};
      auto it = m_emojiImageCache.find(cacheKey);
      if (it == m_emojiImageCache.end())
      {
        auto image = factory->decodeImage(
            {layer.imageBytes.data(), layer.imageBytes.size()});
        it = m_emojiImageCache.emplace(cacheKey, std::move(image)).first;
      }
      if (it->second != nullptr)
      {
        renderer->save();
        // Transform from glyph space: position at bearing and
        // scale from image pixels to glyph extent units.
        float scaleX = layer.imageExtentX / (float)layer.imageWidth;
        float scaleY = layer.imageExtentY / (float)layer.imageHeight;
        renderer->transform(Mat2D(
            scaleX,
            0,
            0,
            scaleY,
            layer.imageBearingX,
            layer.imageBearingY));
        renderer->drawImage(
            it->second.get(),
            ImageSampler::LinearClamp(),
            BlendMode::srcOver,
            info.opacity);
        renderer->restore();
      }
    }
    else
    {
      drawColorGlyphLayer(renderer, factory, layer, info.opacity);
    }
  }
  renderer->restore();
}

void Text::addRun(TextValueRun* run)
{
  m_runs.push_back(run);
  m_allRuns.push_back(run);
}

#ifdef WITH_RIVE_EDITOR
void Text::sortRunsForEditor(
    const std::function<bool(TextValueRun*, TextValueRun*)>& cmp)
{
  if (std::is_sorted(m_runs.begin(), m_runs.end(), cmp) &&
      std::is_sorted(m_allRuns.begin(), m_allRuns.end(), cmp))
  {
    return;
  }
  std::sort(m_runs.begin(), m_runs.end(), cmp);
  std::sort(m_allRuns.begin(), m_allRuns.end(), cmp);
  markShapeDirty();
}
#endif

void Text::addModifierGroup(TextModifierGroup* group)
{
  m_modifierGroups.push_back(group);
}

void Text::markShapeDirty() { markShapeDirty(true); }

void Text::markShapeDirty(bool sendToLayout)
{
  m_listenedRunsDirty = true;
  m_listItemsDirty = true;
  addDirt(ComponentDirt::Path);
  for (TextModifierGroup* group : m_modifierGroups)
  {
    group->clearRangeMaps();
  }
  markWorldTransformDirty();
#ifdef WITH_RIVE_LAYOUT
  if (sendToLayout)
  {
    markLayoutNodeDirty();
  }
#endif
}

void Text::modifierShapeDirty() { addDirt(ComponentDirt::Path); }

void Text::markPaintDirty() { addDirt(ComponentDirt::Paint); }

void Text::styleReferenceWillChange()
{
  // The render list and draw commands hold raw pointers into the outgoing
  // style instance's paint; drop them before it is destroyed.
  clearRenderStyles();
  m_sharedGeometry.clear();
  markShapeDirty();
}

void Text::markListenedRuns()
{
  if (!m_listenedRunsDirty)
  {
    return;
  }
  m_listenedRunsDirty = false;
  Artboard* host = artboard();
  // Only instances run state machines; the file's own artboards don't.
  if (host == nullptr || !host->isInstance())
  {
    return;
  }
  for (auto run : m_allRuns)
  {
    auto style = run->styleReference();
    if (style != nullptr && style->listensToRuns())
    {
      run->isHitTarget(true);
    }
  }
}

bool Text::mayHaveListeningRuns()
{
  for (auto child : children())
  {
    if (child->is<TextStyleReference>() &&
        child->as<TextStyleReference>()->listensToRuns())
    {
      return true;
    }
  }
  // List runs (and bound handles) may pick any of the file's styles.
  return m_file != nullptr && m_file->textStyleShares().anyListensToRuns();
}

void Text::syncStyleListItems()
{
  if (!m_listItemsDirty)
  {
    return;
  }
  m_listItemsDirty = false;
  Artboard* host = artboard();
  // Only instances bind their styles; the file's own artboards don't.
  if (host == nullptr || !host->isInstance())
  {
    return;
  }
  // The list item of the one run drawn with [style], if it's a list run.
  auto itemFor = [this](const TextStyleReference* style) {
    TextValueRun* only = nullptr;
    for (auto run : m_allRuns)
    {
      if (run->styleReference() != style)
      {
        continue;
      }
      if (only != nullptr)
      {
        return rcp<ViewModelInstance>(nullptr);
      }
      only = run;
    }
    for (auto listener : m_valueRunListeners)
    {
      if (only != nullptr && listener->textValueRun() == only)
      {
        return listener->viewModelInstance();
      }
    }
    return rcp<ViewModelInstance>(nullptr);
  };
  for (auto child : children())
  {
    if (child->is<TextStyleReference>())
    {
      auto style = child->as<TextStyleReference>();
      style->listItem(itemFor(style));
    }
  }
  for (auto& style : m_onDemandStyles)
  {
    style->listItem(itemFor(style.get()));
  }
}

void Text::runStateMachines(std::vector<StateMachineInstance*>& out)
{
  for (auto child : children())
  {
    if (child->is<TextStyleReference>())
    {
      if (auto stateMachine = child->as<TextStyleReference>()
                                  ->runStateMachine())
      {
        out.push_back(stateMachine);
      }
    }
  }
  for (auto& style : m_onDemandStyles)
  {
    if (auto stateMachine = style->runStateMachine())
    {
      out.push_back(stateMachine);
    }
  }
}

void Text::styleReferenceDidChange()
{
  // A handle now shows a different style: list runs that matched it by
  // style, and runs bound to one, may need another handle or an on-demand
  // style instead.
  resolveListRunStyles();
  for (auto run : m_runs)
  {
    if (run->isStyleBound())
    {
      run->resolveStyle();
    }
  }
  pruneOnDemandStyles();
  markShapeDirty();
}

TextStyleReference* Text::boundRunStyle(
    ViewModelInstanceArtboard* value,
    const TextValueRun* run)
{
  return globalStyleReference(value, nullptr, run);
}

void Text::runStyleChanged()
{
  pruneOnDemandStyles();
  markShapeDirty();
}

TextStyleReference* Text::resolveListRunStyle(ViewModelInstance* instance)
{
  if (instance == nullptr)
  {
    return nullptr;
  }
  auto globalValue = instance->propertyValue(SymbolType::globalTextStyle);
  auto nameValue = instance->propertyValue(SymbolType::textStyle);
  if (globalValue != nullptr && globalValue->is<ViewModelInstanceArtboard>())
  {
    auto style = globalStyleReference(
        globalValue->as<ViewModelInstanceArtboard>(),
        instance);
    if (style != nullptr)
    {
      return style;
    }
  }
  // An item with no style symbol keeps no style, as before.
  if (globalValue == nullptr && nameValue == nullptr)
  {
    return nullptr;
  }
  if (nameValue != nullptr && nameValue->is<ViewModelInstanceString>())
  {
    auto style = styleReferenceNamed(
        nameValue->as<ViewModelInstanceString>()->propertyValue());
    if (style != nullptr)
    {
      return style;
    }
  }
  return firstStyleReference();
}

TextStyleReference* Text::globalStyleReference(
    ViewModelInstanceArtboard* value,
    ViewModelInstance* item,
    const TextValueRun* owner)
{
  // The style artboard the value names: a runtime-set BindableArtboard
  // (normalized to its file-owned source), else a file artboard index.
  const Artboard* source = nullptr;
  rcp<const File> crossFile;
  if (value->asset() != nullptr)
  {
    auto artboard = value->asset()->artboard();
    if (artboard != nullptr)
    {
      source = artboard->artboardSource();
      auto assetFile = artboard->file();
      if (assetFile != nullptr && assetFile.get() != m_file)
      {
        crossFile = assetFile;
      }
    }
  }
  else if (m_file != nullptr && value->propertyValue() != (uint32_t)-1)
  {
    source = m_file->artboard(value->propertyValue());
  }
  // Not a text style: let the caller fall back.
  if (source == nullptr ||
      TextStyleGlobal::firstTextStylePaint(source) == nullptr)
  {
    return nullptr;
  }

  // A style with a state machine keeps state of its own: each list item
  // (and each run bound to it) gets an instance of its own, which reads that
  // item (see syncStyleListItems). Other styles are shared by the runs
  // naming them.
  TextStyleShareInfo info = crossFile == nullptr && m_file != nullptr
                                ? m_file->textStyleShares().info(source)
                                : TextStyleShareCache::analyze(
                                      source,
                                      crossFile.get());
  rcp<ViewModelInstance> perItem = info.hasStateMachine ? ref_rcp(item)
                                                        : nullptr;
  const TextValueRun* perRun = info.hasStateMachine ? owner : nullptr;

  auto bound = value->boundViewModelInstance();
  // The values an item's own instance copies.
  rcp<ViewModelInstance> handleValues;
  if (bound == nullptr)
  {
    // A handle on this Text showing that style keeps its per-text
    // exposed values: the runs share it, or each item's own instance
    // copies them (what its state machine writes stays its own).
    for (auto child : children())
    {
      if (child->is<TextStyleGlobal>() &&
          child->as<TextStyleGlobal>()->instanceSource() == source)
      {
        auto handle = child->as<TextStyleGlobal>();
        if (perItem == nullptr && perRun == nullptr)
        {
          return handle;
        }
        handleValues = handle->styleViewModelInstance();
        break;
      }
    }
  }

  for (auto& style : m_onDemandStyles)
  {
    if (style->source() == source &&
        style->boundViewModelInstance() == bound.get() &&
        style->item() == perItem.get() && style->owner() == perRun)
    {
      return style.get();
    }
  }
  auto host = artboard();
  m_onDemandStyles.push_back(std::make_unique<TextStyleOnDemand>(
      source,
      bound,
      m_file,
      crossFile,
      host != nullptr ? host->factory() : nullptr,
      host != nullptr ? host->dataContext() : nullptr,
      this,
      perItem,
      handleValues,
      perRun));
  return m_onDemandStyles.back().get();
}

void Text::hostDataContext(rcp<DataContext> value)
{
  for (auto& style : m_onDemandStyles)
  {
    style->hostDataContext(value);
  }
}

void Text::relinkHostDataContext()
{
  for (auto& style : m_onDemandStyles)
  {
    style->relinkHostDataContext();
  }
}

void Text::updateHostedDataBinds()
{
  for (auto& style : m_onDemandStyles)
  {
    style->updateHostedDataBinds();
  }
}

TextStyleReference* Text::styleReferenceNamed(const std::string& name)
{
  for (auto child : children())
  {
    if (child->is<TextStyleReference>() && child->name() == name)
    {
      return child->as<TextStyleReference>();
    }
  }
  return nullptr;
}

TextStyleReference* Text::firstStyleReference()
{
  buildTextStylePaints();
  if (!m_textStylePaints.empty())
  {
    return m_textStylePaints.front();
  }
  for (auto child : children())
  {
    if (child->is<TextStyleReference>())
    {
      return child->as<TextStyleReference>();
    }
  }
  return nullptr;
}

void Text::resolveListRunStyles()
{
  for (auto listener : m_valueRunListeners)
  {
    listener->resolveStyle();
  }
}

void Text::pruneOnDemandStyles()
{
  if (m_onDemandStyles.empty())
  {
    return;
  }
  std::unordered_set<const TextStyleReference*> used;
  // Runs bound to a style draw one too.
  for (auto run : m_runs)
  {
    used.insert(run->styleReference());
  }
  for (auto listener : m_valueRunListeners)
  {
    auto run = listener->textValueRun();
    if (run != nullptr)
    {
      used.insert(run->styleReference());
    }
  }
  auto unused = [&](const std::unique_ptr<TextStyleOnDemand>& style) {
    return used.count(style.get()) == 0;
  };
  if (std::none_of(m_onDemandStyles.begin(), m_onDemandStyles.end(), unused))
  {
    return;
  }
  // The render caches hold raw pointers into the paints about to go.
  clearRenderStyles();
  m_sharedGeometry.clear();
  m_onDemandStyles.erase(
      std::remove_if(m_onDemandStyles.begin(), m_onDemandStyles.end(), unused),
      m_onDemandStyles.end());
  markShapeDirty();
}

bool Text::advanceComponent(float elapsedSeconds, AdvanceFlags flags)
{
  syncStyleListItems();
  bool keepGoing = false;
  bool changed = false;
  for (auto& style : m_onDemandStyles)
  {
    if (style->advance(elapsedSeconds, flags, changed))
    {
      keepGoing = true;
    }
  }
  if (changed)
  {
    // Shape-affecting style properties (font, size, spacing) may have
    // changed.
    markShapeDirty();
  }
  return keepGoing;
}

AdvancingComponent::QuietState Text::quietState()
{
  auto state = QuietState::quiet;
  for (auto& style : m_onDemandStyles)
  {
    switch (style->quietState())
    {
      case QuietState::never:
        return QuietState::never;
      case QuietState::busy:
        state = QuietState::busy;
        break;
      case QuietState::quiet:
        break;
    }
  }
  return state;
}

void Text::alignValueChanged() { markShapeDirty(); }

void Text::sizingValueChanged() { markShapeDirty(); }

void Text::wordBreakValueChanged() { markShapeDirty(); }

void Text::fitFontSizeResizesBoxChanged()
{
  // Only fitFontSize consults the flag, and only to decide what measure()
  // reports, so nothing else needs re-shaping.
  if (overflow() == TextOverflow::fitFontSize)
  {
    markShapeDirty();
  }
}

void Text::overflowValueChanged()
{
  if (effectiveSizing() != TextSizing::autoWidth || overflowAsFixed())
  {
    markShapeDirty();
  }
}

void Text::widthChanged()
{
  if (effectiveSizing() != TextSizing::autoWidth)
  {
    markShapeDirty();
  }
}

void Text::paragraphSpacingChanged()
{
  if (overflow() == TextOverflow::fitFontSize)
  {
    markShapeDirty();
  }
  else
  {
    markPaintDirty();
    // The spacing needs no reshape, but measure() adds it between
    // paragraphs, so a layout sizing this text has to measure it again.
    // buildRenderStyles no longer re-marks the layout on every rebuild.
#ifdef WITH_RIVE_LAYOUT
    markLayoutNodeDirty();
#endif
  }
}

void Text::heightChanged()
{
  if (effectiveSizing() == TextSizing::fixed)
  {
    markShapeDirty();
  }
}

void StyledText::clear()
{
  m_value.clear();
  m_runs.clear();
}

bool StyledText::empty() const { return m_runs.empty(); }

void StyledText::append(
    rcp<Font> font,
    float size,
    float lineHeight,
    float letterSpacing,
    const std::string& text,
    uint16_t styleId)
{
  const uint8_t* ptr = (const uint8_t*)text.data();
  const uint8_t* end = ptr + text.size();
  uint32_t n = 0;
  while (ptr < end && *ptr)
  {
    m_value.push_back(UTF::NextUTF8(&ptr, end));
    n += 1;
  }
  // Shaping takes no empty runs.
  if (n == 0)
  {
    return;
  }
  m_runs.push_back(
      {std::move(font), size, lineHeight, letterSpacing, n, 0, styleId});
}

bool Text::makeStyled(
    StyledText& styledText,
    bool withModifiers,
    float fontScale) const
{
  styledText.clear();
  uint16_t runIndex = 0;
  for (auto valueRun : m_allRuns)
  {
    auto style = valueRun->style();
    const std::string& text = valueRun->text();
    if (style == nullptr || style->font() == nullptr || text.empty())
    {
      runIndex++;
      continue;
    }
    // A custom line height (>= 0) is an absolute value that overrides the
    // font-metric spacing, so it must scale with the font to keep
    // fitFontScale a true uniform scale of the authored layout. The -1
    // sentinel ("derive from font metrics") is left untouched. Letter
    // spacing is likewise an absolute advance added after glyph shaping, so
    // it scales for the same reason.
    float lineHeight = style->lineHeight();
    if (lineHeight >= 0.0f)
    {
      lineHeight *= fontScale;
    }
    styledText.append(
        style->font(),
        style->fontSize() * fontScale,
        lineHeight,
        style->letterSpacing() * fontScale,
        text,
        runIndex++);
  }
  if (withModifiers)
  {
    for (TextModifierGroup* group : m_modifierGroups)
    {
      group->applyShapeModifiers(*this, styledText);
    }
  }
  return !styledText.empty();
}

SimpleArray<SimpleArray<GlyphLine>> Text::BreakLines(
    const SimpleArray<Paragraph>& paragraphs,
    float width,
    TextAlign align,
    TextWrap wrap,
    TextWordBreak wordBreak,
    float minAlignWidth)
{
  bool autoWidth = width == -1.0f;
  float paragraphWidth = width;

  SimpleArray<SimpleArray<GlyphLine>> lines(paragraphs.size());

  size_t paragraphIndex = 0;
  for (auto& para : paragraphs)
  {
    lines[paragraphIndex] = GlyphLine::BreakLines(
        para.runs,
        (autoWidth || wrap == TextWrap::noWrap) ? -1.0f : width,
        wordBreak);
    if (autoWidth)
    {
      paragraphWidth = std::max(
          paragraphWidth,
          GlyphLine::ComputeMaxWidth(lines[paragraphIndex], para.runs));
    }
    paragraphIndex++;
  }
  // Align within the field when it's wider than the text; text that
  // overflows the field aligns within itself (effectively left aligned).
  paragraphWidth = std::max(paragraphWidth, minAlignWidth);
  paragraphIndex = 0;
  for (auto& para : paragraphs)
  {
    GlyphLine::ComputeLineSpacing(
        paragraphIndex == 0,
        lines[paragraphIndex],
        para.runs,
        paragraphWidth,
        align);
    paragraphIndex++;
  }
  return lines;
}

bool Text::modifierRangesNeedShape() const
{
  for (const TextModifierGroup* modifierGroup : m_modifierGroups)
  {
    if (modifierGroup->needsShape())
    {
      return true;
    }
  }
  return false;
}

void Text::onDirty(ComponentDirt value)
{
  // Sometimes a WorldTransform dirt may also affect Path
  if (hasDirt(value, ComponentDirt::WorldTransform))
  {
    for (TextModifierGroup* modifierGroup : m_modifierGroups)
    {
      modifierGroup->onTextWorldTransformDirty();
    }
  }
  if (hasDirt(value, ComponentDirt::Path | ComponentDirt::Paint))
  {
    for (TextStylePaint* style : m_renderStyles)
    {
      style->invalidateStrokeEffects();
    }
  }
}

void Text::update(ComponentDirt value)
{
  Super::update(value);
  markListenedRuns();
  syncStyleListItems();

  if (hasDirt(value, ComponentDirt::Path))
  {
    // We have modifiers that need shaping we'll need to compute the
    // coverage right before we build the actual shape.
    bool precomputeModifierCoverage = modifierRangesNeedShape();
    bool parentIsLayoutNotArtboard = parent()->is<LayoutComponent>() &&
                                     !parent()->is<Artboard>();
    // For fitFontSize, find the largest integer font size that fits the
    // bounds, then shape/lay out the text at that size below.
    float fontScale = overflow() == TextOverflow::fitFontSize ? fitFontScale()
                                                              : 1.0f;
    m_fitFontScale = fontScale;
    if (precomputeModifierCoverage &&
        makeStyled(m_modifierStyledText, false, fontScale))
    {
      const auto& runs = m_modifierStyledText.runs();
      m_modifierShape = runs[0].font->shapeText(
          m_modifierStyledText.unichars(),
          runs);
      m_modifierLines = BreakLines(
          m_modifierShape,
          (effectiveSizing() == TextSizing::autoWidth &&
           !parentIsLayoutNotArtboard)
              ? -1.0f
              : effectiveWidth(),
          align(),
          wrap(),
          wordBreak());
      m_glyphLookup.compute(m_modifierStyledText.unichars(), m_modifierShape);
      uint32_t textSize = (uint32_t)m_modifierStyledText.unichars().size();
      for (TextModifierGroup* group : m_modifierGroups)
      {
        group->computeRangeMap(
            m_modifierStyledText.unichars(),
            m_modifierShape,
            m_modifierLines,
            m_glyphLookup);
        group->computeCoverage(textSize);
      }
    }
    const bool styled = makeStyled(m_styledText, true, fontScale);
    m_shapedKey = measureKey(m_styledText, fontScale);
    if (styled)
    {
      const auto& runs = m_styledText.runs();
      m_shape = runs[0].font->shapeText(m_styledText.unichars(), runs);

      m_lines = BreakLines(
          m_shape,
          (effectiveSizing() == TextSizing::autoWidth &&
           !parentIsLayoutNotArtboard)
              ? -1.0f
              : effectiveWidth(),
          align(),
          wrap(),
          wordBreak());
      if (!precomputeModifierCoverage && haveModifiers())
      {
        m_glyphLookup.compute(m_styledText.unichars(), m_shape);
        uint32_t textSize = (uint32_t)m_styledText.unichars().size();
        for (TextModifierGroup* group : m_modifierGroups)
        {
          group->computeRangeMap(
              m_styledText.unichars(),
              m_shape,
              m_lines,
              m_glyphLookup);
          group->computeCoverage(textSize);
        }
      }
    }
    else
    {
      m_shape = SimpleArray<Paragraph>();
      m_lines = SimpleArray<SimpleArray<GlyphLine>>();
      m_glyphLookup.clear();
    }
    m_ellipsisRun = {};
    m_emojiImageCache.clear();

    // Immediately build render styles so dimensions get computed.
    buildRenderStyles();
  }
  else if (hasDirt(value, ComponentDirt::Paint))
  {
    buildRenderStyles();
  }
  else if (hasDirt(value, ComponentDirt::RenderOpacity))
  {
    // Note that buildRenderStyles does this too, which is why we can get
    // away doing this in the else.
    for (TextStylePaint* style : m_renderStyles)
    {
      style->propagateOpacity(renderOpacity());
    }
    for (TextStylePaint* style : m_textStylePaints)
    {
      if (style->background() != nullptr)
      {
        style->background()->propagateOpacity(renderOpacity());
      }
    }
  }

  if (hasDirt(
          value,
          ComponentDirt::WorldTransform | ComponentDirt::Path |
              ComponentDirt::Paint))
  {
    m_clipPath.rewind();
    m_shapeWorldTransform = m_WorldTransform * m_transform;
    m_clipPath.addPath(m_clipRect, &m_shapeWorldTransform);
  }
  if (m_selectionController != nullptr &&
      hasDirt(value, ComponentDirt::Path | ComponentDirt::Paint))
  {
    m_selectionController->textUpdated(
        this,
        hasDirt(value, ComponentDirt::Path));
  }
}

// What measure() reports depends on, as a hash: the styled text it shapes,
// the scale it shapes at, and the two inputs it reads that a layout hands us
// after its solve (controlSize) -- the effective sizing, from the slot's scale
// types, and the alignment, from its direction. Everything else it reads is
// authored, and changing that marks the layout dirty on its own.
//
// Mixed eight bytes at a time. Every step is a bijection of the running hash,
// so two keys that differ in a single word always differ; hashing byte by
// byte cost about a nanosecond a byte, next to the shaping it sits beside.
uint64_t Text::measureKey(const StyledText& styled, float fontScale) const
{
  uint64_t hash = 0x9e3779b97f4a7c15ull;
  auto mix = [&hash](uint64_t word) {
    hash ^= word;
    hash *= 0xff51afd7ed558ccdull;
    hash ^= hash >> 32;
  };
  auto bits = [](float value) {
    uint32_t out;
    memcpy(&out, &value, sizeof(out));
    return (uint64_t)out;
  };
  mix(bits(fontScale) | (uint64_t)(uint8_t)effectiveSizing() << 32 |
      (uint64_t)(uint8_t)align() << 40);
  for (const TextRun& run : styled.runs())
  {
    mix((uint64_t)(uintptr_t)run.font.get());
    mix(bits(run.size) | bits(run.lineHeight) << 32);
    mix(bits(run.letterSpacing) | (uint64_t)run.unicharCount << 32);
    mix((uint64_t)run.script | (uint64_t)run.styleId << 32 |
        (uint64_t)run.level << 48);
  }
  const auto& unichars = styled.unichars();
  mix(unichars.size());
  size_t i = 0;
  for (; i + 1 < unichars.size(); i += 2)
  {
    mix((uint64_t)unichars[i] | (uint64_t)unichars[i + 1] << 32);
  }
  if (i < unichars.size())
  {
    mix(unichars[i]);
  }
  return hash;
}

Vec2D Text::measure(Vec2D maxSize)
{
  auto measuringWidth = 0.0f;
  switch (effectiveSizing())
  {
    case TextSizing::autoHeight:
    case TextSizing::fixed:
      // The authored width only governs while the text owns its width
      // axis. Under a layout that boxes it -- fill, or a fixed slot the
      // layout resolves -- the authored value is stale and the real
      // width is the one being offered in maxSize, so leave it
      // unbounded and let the min() below take the offer. Reading
      // m_layoutWidth instead would not work: controlSize writes it
      // after the solve, so it is still NAN here.
      measuringWidth = layoutOwnsWidth() ? std::numeric_limits<float>::max()
                                         : width();
      break;
    default:
      measuringWidth = std::numeric_limits<float>::max();
      break;
  }
  // fitFontSize shrinks the font until the text fits its box, so the box we
  // report back to the layout engine has to be measured at the *fitted*
  // size. Measuring at the authored size hands the layout a slot taller
  // than the text that will actually be drawn into it, which shows up as
  // dead space under a hug-height text. The fit runs against the space the
  // layout is offering here (maxSize/measuringWidth), not against
  // m_layoutWidth/Height -- those still hold the previous pass's slot.
  const float fitWidth = std::min(maxSize.x, measuringWidth);
  float fontScale = 1.0f;
  // Gate this the way fitFontScale() gates the update side -- overflow is
  // inert below 7.3 (FileFeatures::layoutSizesBox) -- minus one clause.
  if (overflow() == TextOverflow::fitFontSize &&
      fitFontSizeResizesBoxActive() &&
      hasFileFeature(FileFeatures::layoutSizesBox) &&
      fitWidth != std::numeric_limits<float>::max())
  {
    fontScale = fitFontScale(fitWidth, maxSize.y);
  }
  const bool styled = makeStyled(m_styledText, true, fontScale);
  m_measuredKey = measureKey(m_styledText, fontScale);
  if (styled)
  {
    const float paragraphSpace = paragraphSpacing() * fontScale;
    const auto& runs = m_styledText.runs();
    auto shape = runs[0].font->shapeText(m_styledText.unichars(), runs);
    auto measuringWrap = maxSize.x == std::numeric_limits<float>::max() &&
                                 effectiveSizing() != TextSizing::autoHeight
                             ? TextWrap::noWrap
                             : wrap();
    auto lines = BreakLines(
        shape,
        fitWidth,
        align(),
        measuringWrap,
        wordBreak());
    float y = 0;
    float computedHeight = 0.0f;
    float minY = 0;
    int paragraphIndex = 0;
    float maxWidth = 0;

    if (textOrigin() == TextOrigin::baseline && !lines.empty() &&
        !lines[0].empty())
    {
      y -= lines[0][0].baseline;
      minY = y;
    }
    int ellipsisLine = -1;
    bool wantEllipsis = overflow() == TextOverflow::ellipsis &&
                        sizing() == TextSizing::fixed;

    for (const SimpleArray<GlyphLine>& paragraphLines : lines)
    {
      const Paragraph& paragraph = shape[paragraphIndex++];
      for (const GlyphLine& line : paragraphLines)
      {
        const GlyphRun& endRun = paragraph.runs[line.endRunIndex];
        const GlyphRun& startRun = paragraph.runs[line.startRunIndex];
        float width = endRun.xpos[line.endGlyphIndex] -
                      startRun.xpos[line.startGlyphIndex];
        if (width > maxWidth)
        {
          maxWidth = width;
        }
        if (wantEllipsis && y + line.bottom > maxSize.y)
        {
          if (ellipsisLine == -1)
          {
            // Nothing fits, just show the first line and ellipse
            // it.
            computedHeight = y + line.bottom;
          }
          goto doneMeasuring;
        }
        ellipsisLine++;
        computedHeight = y + line.bottom;
      }
      if (!paragraphLines.empty())
      {
        y += paragraphLines.back().bottom;
      }
      y += paragraphSpace;
    }
  doneMeasuring:
    // Match the rendered box: trim the ascent/descent band for auto sizing.
    float topTrim = 0.0f;
    float bottomTrim = 0.0f;
    computeVerticalTrim(
        lines,
        shape,
        verticalTrimTop(),
        verticalTrimBottom(),
        topTrim,
        bottomTrim);
    Vec2D bounds;
    switch (sizing())
    {
      case TextSizing::autoWidth:
        bounds = Vec2D(
            maxWidth,
            std::max(minY, computedHeight - topTrim - bottomTrim));
        break;
      case TextSizing::autoHeight:
        bounds = Vec2D(
            width(),
            std::max(minY, computedHeight - topTrim - bottomTrim));
        break;
      case TextSizing::fixed:
        bounds = Vec2D(width(), minY + height());
        break;
    }
    return Vec2D(std::min(maxSize.x, bounds.x), std::min(maxSize.y, bounds.y));
  }
  return Vec2D();
}

AABB Text::localBounds() const
{
  float width = m_bounds.width();
  float height = m_bounds.height();
  return AABB::fromLTWH(
      m_bounds.minX - width * originX(),
      m_bounds.minY - height * originY(),
      width,
      height);
}

Core* Text::hitTest(HitInfo*, const Mat2D&)
{
  if (renderOpacity() == 0.0f)
  {
    return nullptr;
  }

  return nullptr;
}

void Text::originValueChanged()
{
  markPaintDirty();
  markWorldTransformDirty();
  // A baseline origin moves the first line up, which measure() reports as a
  // different height, so a layout sizing this text has to measure it again.
#ifdef WITH_RIVE_LAYOUT
  markLayoutNodeDirty();
#endif
}

void Text::originXChanged()
{
  markPaintDirty();
  markWorldTransformDirty();
}
void Text::originYChanged()
{
  markPaintDirty();
  markWorldTransformDirty();
}

void Text::verticalTrimValueChanged()
{
  // Trim affects both the rendered box and the layout-measured size, so go
  // through the shape/layout path like sizing does.
  markShapeDirty();
}

#else
// Text disabled.
Text::~Text() {}
void Text::draw(Renderer* renderer) {}
Core* Text::hitTest(HitInfo*, const Mat2D&) { return nullptr; }
void Text::addRun(TextValueRun* run) {}
void Text::addModifierGroup(TextModifierGroup* group) {}
void Text::markShapeDirty(bool sendToLayout) {}
void Text::markShapeDirty() {}
void Text::styleReferenceWillChange() {}
void Text::styleReferenceDidChange() {}
void Text::hostDataContext(rcp<DataContext> value) {}
void Text::relinkHostDataContext() {}
void Text::updateHostedDataBinds() {}
bool Text::advanceComponent(float elapsedSeconds, AdvanceFlags flags)
{
  return false;
}
AdvancingComponent::QuietState Text::quietState() { return QuietState::quiet; }
void Text::update(ComponentDirt value) {}
void Text::onDirty(ComponentDirt value) {}
void Text::alignValueChanged() {}
void Text::sizingValueChanged() {}
void Text::wordBreakValueChanged() {}
void Text::overflowValueChanged() {}
void Text::fitFontSizeResizesBoxChanged() {}
void Text::widthChanged() {}
void Text::heightChanged() {}
void Text::markPaintDirty() {}
void Text::modifierShapeDirty() {}
bool Text::modifierRangesNeedShape() const { return false; }
const TextStylePaint* Text::styleFromShaperId(uint16_t id) const
{
  return nullptr;
}
void Text::paragraphSpacingChanged() {}
AABB Text::localBounds() const { return AABB(); }
void Text::originValueChanged() {}
void Text::originXChanged() {}
void Text::originYChanged() {}
void Text::verticalTrimValueChanged() {}
Vec2D Text::measureLayout(
    float width,
    LayoutMeasureMode widthMode,
    float height,
    LayoutMeasureMode heightMode)
{
  return Vec2D();
}
void Text::controlSize(
    Vec2D size,
    LayoutScaleType widthScaleType,
    LayoutScaleType heightScaleType,
    LayoutDirection direction)
{}
#endif

StatusCode Text::import(ImportStack& importStack)
{
  // A layout has always sized the text itself (effectiveWidth/Height), but
  // before 7.3 an auto-sized text still took its *box* from the content, so
  // the box could disagree with the slot and every overflow mode stayed
  // inert. Keep that for those files; newer ones box to the slot. See
  // File::minorVersion.
  int major = importStack.majorVersion();
  int minor = importStack.minorVersion();
  auto atLeast = [major, minor](int wantMinor) {
    return major > 7 || (major == 7 && minor >= wantMinor);
  };
  m_fileFeatures = FileFeatures::none;
  if (atLeast(3))
  {
    m_fileFeatures |= FileFeatures::layoutSizesBox;
  }
  // 7.4 measures a fitFontSize text at its fitted size. Older files laid
  // their layouts out against the unshrunk box, so honoring the flag there
  // would reflow them; fitFontSizeResizesBox defaults to true and those
  // files never wrote it.
  if (atLeast(4))
  {
    m_fileFeatures |= FileFeatures::fitFontSizeResizesBox;
  }
  return Super::import(importStack);
}

Core* Text::clone() const
{
  Text* twin = TextBase::clone()->as<Text>();
  twin->m_fileFeatures = m_fileFeatures;
  twin->m_file = m_file;
  return twin;
}

Vec2D Text::layoutBaseTranslation(LayoutParticipant* participant) const
{
  assert(participant != nullptr);
  return Vec2D(
      participant->resolvedLeft() + originX() * participant->resolvedWidth(),
      participant->resolvedTop() + originY() * participant->resolvedHeight());
}

void Text::composeWorldTransform()
{
  // The base composes m_WorldTransform = parentWorld * m_Transform; insert
  // the origin-based slot base instead when participating (text sizes via its
  // own layout, not a geometric scale).
#ifdef WITH_RIVE_LAYOUT
  auto* participant = layoutParticipant();
  if (participant != nullptr && m_ParentTransformComponent != nullptr)
  {
    Mat2D base = Mat2D::fromTranslation(layoutBaseTranslation(participant));
    m_WorldTransform = m_ParentTransformComponent->worldTransform() * base *
                       m_Transform;
    return;
  }
#endif
  Super::composeWorldTransform();
}

void Text::updateConstraints()
{
#ifdef WITH_RIVE_LAYOUT
  auto* participant = layoutParticipant();
  if (participant != nullptr)
  {
    participant->applyLayoutConstraints();
  }
#endif
  Super::updateConstraints();
}

LayoutParticipant* Text::layoutParticipant() const
{
  for (auto* child : children())
  {
    if (child->is<LayoutParticipant>())
    {
      return child->as<LayoutParticipant>();
    }
  }
  return nullptr;
}

bool Text::isParticipatingInLayout() const
{
  return layoutParticipant() != nullptr;
}

bool Text::layoutOwnsWidth() const
{
#ifdef WITH_RIVE_LAYOUT
  if (auto* participant = layoutParticipant())
  {
    const auto widthScaleType = (LayoutScaleType)
                                    participant->layoutWidthScaleType();
    return widthScaleType == LayoutScaleType::fixed ||
           widthScaleType == LayoutScaleType::fill;
  }
#endif
  return false;
}

TextAlign Text::align() const
{
  auto val = (TextAlign)alignValue();
  if (m_layoutDirection == LayoutDirection::inherit || val == TextAlign::center)
  {
    return val;
  }
  return m_layoutDirection == LayoutDirection::ltr ? TextAlign::left
                                                   : TextAlign::right;
}

void Text::updateList(std::vector<rcp<ViewModelInstanceListItem>>* list)
{
#ifdef WITH_RIVE_TEXT
  buildTextStylePaints();
  m_allRuns.clear();
  m_allRuns.assign(m_runs.begin(), m_runs.end());
  auto currentSize = m_valueRunListeners.size();
  size_t index = 0;
  for (auto& listItem : *list)
  {
    auto instance = listItem->viewModelInstance();
    if (instance)
    {
      TextValueRun* textRun;
      if (index < currentSize)
      {
        auto textRunListener = m_valueRunListeners[index];
        textRunListener->remap(instance);
        textRun = textRunListener->textValueRun();
      }
      else
      {
        textRun = new TextValueRun();
        textRun->textComponent(this);
        auto textRunListener = new TextValueRunListener(
            textRun,
            instance,
            this);
        m_valueRunListeners.push_back(textRunListener);
      }
      if (textRun)
      {
        m_allRuns.push_back(textRun);
      }
      index++;
    }
  }
  while (m_valueRunListeners.size() > index)
  {
    auto valueRun = m_valueRunListeners.back();
    m_valueRunListeners.pop_back();
    delete valueRun;
  }
  pruneOnDemandStyles();
  markShapeDirty();
#endif
}

#ifdef WITH_RIVE_TEXT
void Text::buildTextStylePaints()
{
  if (m_textStylePaints.size() == 0)
  {
    for (auto& child : children())
    {
      if (child->coreType() == TextStylePaint::typeKey)
      {
        m_textStylePaints.push_back(child->as<TextStylePaint>());
      }
    }
  }
}
#endif

BoundsFidelity Text::paintedWorldBounds(AABB* out)
{
  const BoundsFidelity fidelity = paintedBoundsFromLocal(
      localBounds(),
      worldTransform(),
      nullptr,
      out);
  if (fidelity == BoundsFidelity::none)
  {
    return fidelity;
  }
  // Never better than approximate: see the note on the declaration. The ink
  // can reach past the layout box, so an exact claim here would crop glyphs.
  return BoundsFidelity::approximate;
}

#ifdef WITH_RIVE_EDITOR
void Text::editorPrepareForDestruction()
{
#ifdef WITH_RIVE_TEXT
  if (m_selectionController != nullptr)
    m_selectionController->remove(this);
  for (auto* listener : m_valueRunListeners)
    delete listener;
  m_valueRunListeners.clear();
#endif
  Component::editorPrepareForDestruction();
}

#endif
