/*
 * Copyright 2019 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "modules/skottie/src/text/TextAdapter.h"

#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkContourMeasure.h"
#include "include/core/SkFont.h"
#include "include/core/SkFontMgr.h"
#include "include/core/SkM44.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPath.h"
#include "include/core/SkRect.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSpan.h"
#include "include/core/SkString.h"
#include "include/core/SkTypes.h"
#include "include/private/SkTPin.h"
#include "include/private/SkTo.h"
#include "include/utils/SkTextUtils.h"
#include "modules/jsonreader/SkJSONReader.h"
#include "modules/skottie/include/Skottie.h"
#include "modules/skottie/include/SkottieProperty.h"
#include "modules/skottie/src/SkottieJson.h"
#include "modules/skottie/src/SkottiePriv.h"
#include "modules/skottie/src/text/RangeSelector.h"  // IWYU pragma: keep
#include "modules/skottie/src/text/TextAnimator.h"
#include "modules/sksg/include/SkSGDraw.h"
#include "modules/sksg/include/SkSGGeometryNode.h"
#include "modules/sksg/include/SkSGGroup.h"
#include "modules/sksg/include/SkSGPaint.h"
#include "modules/sksg/include/SkSGPath.h"
#include "modules/sksg/include/SkSGRect.h"
#include "modules/sksg/include/SkSGRenderEffect.h"
#include "modules/sksg/include/SkSGRenderNode.h"
#include "modules/sksg/include/SkSGTransform.h"
#include "modules/sksg/src/SkSGTransformPriv.h"
#include "modules/skshaper/include/SkShaper_factory.h"
#include "src/core/SkPathPriv.h"

#include <algorithm>
#include <array>
#include <cmath>
#include <cstddef>
#include <limits>
#include <tuple>
#include <utility>

namespace sksg {
class InvalidationController;
}

// Enable for text layout debugging.
#define SHOW_LAYOUT_BOXES 0

namespace skottie::internal {

namespace {

class GlyphTextNode final : public sksg::GeometryNode {
public:
    explicit GlyphTextNode(Shaper::ShapedGlyphs&& glyphs) : fGlyphs(std::move(glyphs)) {}

    ~GlyphTextNode() override = default;

    const Shaper::ShapedGlyphs* glyphs() const { return &fGlyphs; }

protected:
    SkRect onRevalidate(sksg::InvalidationController*, const SkMatrix&) override {
        return fGlyphs.computeBounds(Shaper::ShapedGlyphs::BoundsType::kTight);
    }

    void onDraw(SkCanvas* canvas, const SkPaint& paint) const override {
        fGlyphs.draw(canvas, {0,0}, paint);
    }

    void onClip(SkCanvas* canvas, bool antiAlias) const override {
        canvas->clipPath(this->asPath(), antiAlias);
    }

    bool onContains(const SkPoint& p) const override {
        return this->asPath().contains(p.x(), p.y());
    }

    SkPath onAsPath() const override {
        // TODO
        return SkPath();
    }

private:
    const Shaper::ShapedGlyphs fGlyphs;
};

static float align_factor(SkTextUtils::Align a) {
    switch (a) {
        case SkTextUtils::kLeft_Align  : return 0.0f;
        case SkTextUtils::kCenter_Align: return 0.5f;
        case SkTextUtils::kRight_Align : return 1.0f;
    }

    SkUNREACHABLE;
}

} // namespace

class TextAdapter::GlyphDecoratorNode final : public sksg::Group {
public:
    GlyphDecoratorNode(sk_sp<GlyphDecorator> decorator, float scale)
        : fDecorator(std::move(decorator))
        , fScale(scale)
    {}

    ~GlyphDecoratorNode() override = default;

    void updateFragmentData(const std::vector<TextAdapter::FragmentRec>& recs) {
        fFragCount = recs.size();

        SkASSERT(!fFragInfo);
        fFragInfo = std::make_unique<FragmentInfo[]>(recs.size());

        for (size_t i = 0; i < recs.size(); ++i) {
            const auto& rec = recs[i];
            fFragInfo[i] = {rec.fGlyphs, rec.fMatrixNode, rec.fAdvance};
        }

        SkASSERT(!fDecoratorInfo);
        fDecoratorInfo = std::make_unique<GlyphDecorator::GlyphInfo[]>(recs.size());
    }

    SkRect onRevalidate(sksg::InvalidationController* ic, const SkMatrix& ctm) override {
        const auto child_bounds = INHERITED::onRevalidate(ic, ctm);

        for (size_t i = 0; i < fFragCount; ++i) {
            const auto* glyphs = fFragInfo[i].fGlyphs;
            fDecoratorInfo[i].fBounds =
                    glyphs->computeBounds(Shaper::ShapedGlyphs::BoundsType::kTight);
            fDecoratorInfo[i].fMatrix = sksg::TransformPriv::As<SkMatrix>(fFragInfo[i].fMatrixNode);

            fDecoratorInfo[i].fCluster = glyphs->fClusters.empty() ? 0 : glyphs->fClusters.front();
            fDecoratorInfo[i].fAdvance = fFragInfo[i].fAdvance;
        }

        return child_bounds;
    }

    void onRender(SkCanvas* canvas, const RenderContext* ctx) const override {
        auto local_ctx = ScopedRenderContext(canvas, ctx).setIsolation(this->bounds(),
                                                                       canvas->getTotalMatrix(),
                                                                       true);
        this->INHERITED::onRender(canvas, local_ctx);

        fDecorator->onDecorate(canvas, {
            SkSpan(fDecoratorInfo.get(), fFragCount),
            fScale
        });
    }

private:
    struct FragmentInfo {
        const Shaper::ShapedGlyphs* fGlyphs;
        sk_sp<sksg::Matrix<SkM44>>  fMatrixNode;
        float                       fAdvance;
    };

    const sk_sp<GlyphDecorator>                  fDecorator;
    const float                                  fScale;

    std::unique_ptr<FragmentInfo[]>              fFragInfo;
    std::unique_ptr<GlyphDecorator::GlyphInfo[]> fDecoratorInfo;
    size_t                                       fFragCount;

    using INHERITED = Group;
};

// Text path semantics
//
//   * glyphs are positioned on the path based on their horizontal/x anchor point, interpreted as
//     a distance along the path
//
//   * horizontal alignment is applied relative to the path start/end points
//
//   * "Reverse Path" allows reversing the path direction
//
//   * "Perpendicular To Path" determines whether glyphs are rotated to be perpendicular
//      to the path tangent, or not (just positioned).
//
//   * two controls ("First Margin" and "Last Margin") allow arbitrary offseting along the path,
//     depending on horizontal alignement:
//       - left:   offset = first margin
//       - center: offset = first margin + last margin
//       - right:  offset = last margin
//
//   * extranormal path positions (d < 0, d > path len) are allowed
//       - closed path: the position wraps around in both directions
//       - open path: extrapolates from extremes' positions/slopes
//
struct TextAdapter::PathInfo {
    ShapeValue  fPath;
    ScalarValue fPathFMargin       = 0,
                fPathLMargin       = 0,
                fPathPerpendicular = 0,
                fPathReverse       = 0;

    void updateContourData() {
        const auto reverse = fPathReverse != 0;

        if (fPath != fCurrentPath || reverse != fCurrentReversed) {
            // reinitialize cached contour data
            auto path = static_cast<SkPath>(fPath);
            if (reverse) {
                path = SkPathPriv::ReversePath(path);
            }

            SkContourMeasureIter iter(path, /*forceClosed = */false);
            fCurrentMeasure  = iter.next();
            fCurrentClosed   = path.isLastContourClosed();
            fCurrentReversed = reverse;
            fCurrentPath     = fPath;

            // AE paths are always single-contour (no moves allowed).
            SkASSERT(!iter.next());
        }
    }

    float pathLength() const {
        SkASSERT(fPath == fCurrentPath);
        SkASSERT((fPathReverse != 0) == fCurrentReversed);

        return fCurrentMeasure ? fCurrentMeasure->length() : 0;
    }

    SkM44 getMatrix(float distance, SkTextUtils::Align alignment) const {
        SkASSERT(fPath == fCurrentPath);
        SkASSERT((fPathReverse != 0) == fCurrentReversed);

        if (!fCurrentMeasure) {
            return SkM44();
        }

        const auto path_len = fCurrentMeasure->length();

        // First/last margin adjustment also depends on alignment.
        switch (alignment) {
            case SkTextUtils::Align::kLeft_Align:   distance += fPathFMargin; break;
            case SkTextUtils::Align::kCenter_Align: distance += fPathFMargin +
                                                                fPathLMargin; break;
            case SkTextUtils::Align::kRight_Align:  distance += fPathLMargin; break;
        }

        // For closed paths, extranormal distances wrap around the contour.
        if (fCurrentClosed) {
            distance = std::fmod(distance, path_len);
            if (distance < 0) {
                distance += path_len;
            }
            SkASSERT(0 <= distance && distance <= path_len);
        }

        SkPoint pos;
        SkVector tan;
        if (!fCurrentMeasure->getPosTan(distance, &pos, &tan)) {
            return SkM44();
        }

        // For open paths, extranormal distances are extrapolated from extremes.
        // Note:
        //   - getPosTan above clamps to the extremes
        //   - the extrapolation below only kicks in for extranormal values
        const auto underflow = std::min(0.0f, distance),
                   overflow  = std::max(0.0f, distance - path_len);
        pos += tan*(underflow + overflow);

        auto m = SkM44::Translate(pos.x(), pos.y());

        // The "perpendicular" flag controls whether fragments are positioned and rotated,
        // or just positioned.
        if (fPathPerpendicular != 0) {
            m = m * SkM44::Rotate({0,0,1}, std::atan2(tan.y(), tan.x()));
        }

        return m;
    }

private:
    // Cached contour data.
    ShapeValue              fCurrentPath;
    sk_sp<SkContourMeasure> fCurrentMeasure;
    bool                    fCurrentReversed = false,
                            fCurrentClosed   = false;
};

sk_sp<TextAdapter> TextAdapter::Make(const skjson::ObjectValue& jlayer,
                                     const AnimationBuilder* abuilder,
                                     sk_sp<SkFontMgr> fontmgr,
                                     sk_sp<CustomFont::GlyphCompMapper> custom_glyph_mapper,
                                     sk_sp<Logger> logger,
                                     sk_sp<::SkShapers::Factory> factory) {
    // General text node format:
    // "t": {
    //    "a": [], // animators (see TextAnimator)
    //    "d": {
    //        "k": [
    //            {
    //                "s": {
    //                    "f": "Roboto-Regular",
    //                    "fc": [
    //                        0.42,
    //                        0.15,
    //                        0.15
    //                    ],
    //                    "j": 1,
    //                    "lh": 60,
    //                    "ls": 0,
    //                    "s": 50,
    //                    "t": "text align right",
    //                    "tr": 0
    //                },
    //                "t": 0
    //            }
    //        ],
    //        "sid": "optionalSlotID"
    //    },
    //    "m": { // more options
    //           "g": 1,     // Anchor Point Grouping
    //           "a": {...}  // Grouping Alignment
    //         },
    //    "p": { // path options
    //           "a": 0,   // force alignment
    //           "f": {},  // first margin
    //           "l": {},  // last margin
    //           "m": 1,   // mask index
    //           "p": 1,   // perpendicular
    //           "r": 0    // reverse path
    //         }

    // },

    const skjson::ObjectValue* jt = jlayer["t"];
    const skjson::ObjectValue* jd = jt ? static_cast<const skjson::ObjectValue*>((*jt)["d"])
                                       : nullptr;
    if (!jd) {
        abuilder->log(Logger::Level::kError, &jlayer, "Invalid text layer.");
        return nullptr;
    }

    // "More options"
    const skjson::ObjectValue* jm = (*jt)["m"];
    static constexpr auto gGroupingMap = std::to_array<AnchorPointGrouping>({
            AnchorPointGrouping::kCharacter,  // 'g': 1
            AnchorPointGrouping::kWord,       // 'g': 2
            AnchorPointGrouping::kLine,       // 'g': 3
            AnchorPointGrouping::kAll,        // 'g': 4
    });
    const auto apg = jm
            ? SkTPin<int>(ParseDefault<int>((*jm)["g"], 1), 1, std::size(gGroupingMap))
            : 1;

    auto adapter = sk_sp<TextAdapter>(new TextAdapter(std::move(fontmgr),
                                                      std::move(custom_glyph_mapper),
                                                      std::move(logger),
                                                      std::move(factory),
                                                      gGroupingMap[SkToSizeT(apg - 1)]));

    adapter->bind(*abuilder, jd, adapter->fText.fCurrentValue);
    if (jm) {
        adapter->bind(*abuilder, (*jm)["a"], adapter->fGroupingAlignment);
    }

    // Animators
    if (const skjson::ArrayValue* janimators = (*jt)["a"]) {
        adapter->fAnimators.reserve(janimators->size());

        for (const skjson::ObjectValue* janimator : *janimators) {
            if (auto animator = TextAnimator::Make(janimator, abuilder, adapter.get())) {
                adapter->fHasBlurAnimator         |= animator->hasBlur();
                adapter->fRequiresAnchorPoint     |= animator->requiresAnchorPoint();
                adapter->fRequiresLineAdjustments |= animator->requiresLineAdjustments();

                adapter->fAnimators.push_back(std::move(animator));
            }
        }
    }

    // Optional text path
    const auto attach_path = [&](const skjson::ObjectValue* jpath) -> std::unique_ptr<PathInfo> {
        if (!jpath) {
            return nullptr;
        }

        // the actual path is identified as an index in the layer mask stack
        const auto mask_index =
                ParseDefault<size_t>((*jpath)["m"], std::numeric_limits<size_t>::max());
        const skjson::ArrayValue* jmasks = jlayer["masksProperties"];
        if (!jmasks || mask_index >= jmasks->size()) {
            return nullptr;
        }

        const skjson::ObjectValue* mask = (*jmasks)[mask_index];
        if (!mask) {
            return nullptr;
        }

        auto pinfo = std::make_unique<PathInfo>();
        adapter->bind(*abuilder, (*mask)["pt"], &pinfo->fPath);
        adapter->bind(*abuilder, (*jpath)["f"], &pinfo->fPathFMargin);
        adapter->bind(*abuilder, (*jpath)["l"], &pinfo->fPathLMargin);
        adapter->bind(*abuilder, (*jpath)["p"], &pinfo->fPathPerpendicular);
        adapter->bind(*abuilder, (*jpath)["r"], &pinfo->fPathReverse);

        // TODO: force align support

        // Historically, these used to be exported as static properties.
        // Attempt parsing both ways, for backward compat.
        skottie::Parse((*jpath)["p"], &pinfo->fPathPerpendicular);
        skottie::Parse((*jpath)["r"], &pinfo->fPathReverse);

        // Path positioning requires anchor point info.
        adapter->fRequiresAnchorPoint = true;

        return pinfo;
    };

    adapter->fPathInfo = attach_path((*jt)["p"]);
    abuilder->dispatchTextProperty(adapter, jd);

    return adapter;
}

TextAdapter::TextAdapter(sk_sp<SkFontMgr> fontmgr,
                         sk_sp<CustomFont::GlyphCompMapper> custom_glyph_mapper,
                         sk_sp<Logger> logger,
                         sk_sp<SkShapers::Factory> factory,
                         AnchorPointGrouping apg)
    : fRoot(sksg::Group::Make())
    , fFontMgr(std::move(fontmgr))
    , fCustomGlyphMapper(std::move(custom_glyph_mapper))
    , fLogger(std::move(logger))
    , fShapingFactory(std::move(factory))
    , fAnchorPointGrouping(apg)
    , fHasBlurAnimator(false)
    , fRequiresAnchorPoint(false)
    , fRequiresLineAdjustments(false) {}

TextAdapter::~TextAdapter() = default;

std::vector<sk_sp<sksg::RenderNode>>
TextAdapter::buildGlyphCompNodes(Shaper::ShapedGlyphs& glyphs) const {
    std::vector<sk_sp<sksg::RenderNode>> draws;

    if (fCustomGlyphMapper) {
        size_t run_offset = 0;
        for (auto& run : glyphs.fRuns) {
            for (size_t i = 0; i < run.fSize; ++i) {
                const size_t goffset = run_offset + i;
                const SkGlyphID  gid = glyphs.fGlyphIDs[goffset];

                if (auto gcomp = fCustomGlyphMapper->getGlyphComp(run.fFont.getTypeface(), gid)) {
                    // Position and scale the "glyph".
                    const auto m = SkMatrix::Translate(glyphs.fGlyphPos[goffset])
                                 * SkMatrix::Scale(fText->fTextSize*fTextShapingScale,
                                                   fText->fTextSize*fTextShapingScale);

                    draws.push_back(sksg::TransformEffect::Make(std::move(gcomp), m));

                    // Remove all related data from the fragment, so we don't attempt to render
                    // this as a regular glyph.
                    SkASSERT(glyphs.fGlyphIDs.size() > goffset);
                    glyphs.fGlyphIDs.erase(glyphs.fGlyphIDs.begin() + goffset);
                    SkASSERT(glyphs.fGlyphPos.size() > goffset);
                    glyphs.fGlyphPos.erase(glyphs.fGlyphPos.begin() + goffset);
                    if (!glyphs.fClusters.empty()) {
                        SkASSERT(glyphs.fClusters.size() > goffset);
                        glyphs.fClusters.erase(glyphs.fClusters.begin() + goffset);
                    }
                    i         -= 1;
                    run.fSize -= 1;
                }
            }
            run_offset += run.fSize;
        }
    }

    return draws;
}

void TextAdapter::addFragment(Shaper::Fragment& frag, sksg::Group* container) {
    // For a given shaped fragment, build a corresponding SG fragment:
    //
    //   [TransformEffect] -> [Transform]
    //     [Group]
    //       [Draw] -> [GlyphTextNode*] [FillPaint]    // SkTypeface-based glyph.
    //       [Draw] -> [GlyphTextNode*] [StrokePaint]  // SkTypeface-based glyph.
    //       [CompRenderTree]                          // Comp glyph.
    //       ...
    //

    FragmentRec rec;
    rec.fOrigin     = frag.fOrigin;
    rec.fAdvance    = frag.fAdvance;
    rec.fAscent     = frag.fAscent;
    rec.fMatrixNode = sksg::Matrix<SkM44>::Make(SkM44::Translate(frag.fOrigin.x(),
                                                                 frag.fOrigin.y()));

    // Start off substituting existing comp nodes for all composition-based glyphs.
    std::vector<sk_sp<sksg::RenderNode>> draws = this->buildGlyphCompNodes(frag.fGlyphs);

    // Use a regular GlyphTextNode for the remaining glyphs (backed by a real SkTypeface).
    auto text_node = sk_make_sp<GlyphTextNode>(std::move(frag.fGlyphs));
    rec.fGlyphs = text_node->glyphs();

    draws.reserve(draws.size() +
                  static_cast<size_t>(fText->fHasFill) +
                  static_cast<size_t>(fText->fHasStroke));

    SkASSERT(fText->fHasFill || fText->fHasStroke);

    auto add_fill = [&]() {
        if (fText->fHasFill) {
            rec.fFillColorNode = sksg::Color::Make(fText->fFillColor);
            rec.fFillColorNode->setAntiAlias(true);
            draws.push_back(sksg::Draw::Make(text_node, rec.fFillColorNode));
        }
    };
    auto add_stroke = [&] {
        if (fText->fHasStroke) {
            rec.fStrokeColorNode = sksg::Color::Make(fText->fStrokeColor);
            rec.fStrokeColorNode->setAntiAlias(true);
            rec.fStrokeColorNode->setStyle(SkPaint::kStroke_Style);
            rec.fStrokeColorNode->setStrokeWidth(fText->fStrokeWidth * fTextShapingScale);
            rec.fStrokeColorNode->setStrokeJoin(fText->fStrokeJoin);
            draws.push_back(sksg::Draw::Make(text_node, rec.fStrokeColorNode));
        }
    };

    if (fText->fPaintOrder == TextPaintOrder::kFillStroke) {
        add_fill();
        add_stroke();
    } else {
        add_stroke();
        add_fill();
    }

    SkASSERT(!draws.empty());

    if (SHOW_LAYOUT_BOXES) {
        // visualize fragment ascent boxes
        auto box_color = sksg::Color::Make(0xff0000ff);
        box_color->setStyle(SkPaint::kStroke_Style);
        box_color->setStrokeWidth(1);
        box_color->setAntiAlias(true);
        auto box = SkRect::MakeLTRB(0, rec.fAscent, rec.fAdvance, 0);
        draws.push_back(sksg::Draw::Make(sksg::Rect::Make(box), std::move(box_color)));
    }

    draws.shrink_to_fit();

    auto draws_node = (draws.size() > 1)
            ? sksg::Group::Make(std::move(draws))
            : std::move(draws[0]);

    if (fHasBlurAnimator) {
        // Optional blur effect.
        rec.fBlur = sksg::BlurImageFilter::Make();
        draws_node = sksg::ImageFilterEffect::Make(std::move(draws_node), rec.fBlur);
    }

    container->addChild(sksg::TransformEffect::Make(std::move(draws_node), rec.fMatrixNode));
    fFragments.push_back(std::move(rec));
}

void TextAdapter::buildDomainMaps(const Shaper::Result& shape_result) {
    fMaps.fNonWhitespaceMap.clear();
    fMaps.fWordsMap.clear();
    fMaps.fLinesMap.clear();

    size_t i          = 0,
           line       = 0,
           line_start = 0,
           word_start = 0;

    float word_advance = 0,
          word_ascent  = 0,
          line_advance = 0,
          line_ascent  = 0;

    bool in_word = false;

    // TODO: use ICU for building the word map?
    for (; i  < shape_result.fFragments.size(); ++i) {
        const auto& frag = shape_result.fFragments[i];
        const bool is_new_line = frag.fLineIndex != line;

        if (frag.fIsWhitespace || is_new_line) {
            // Both whitespace and new lines break words.
            if (in_word) {
                in_word = false;
                fMaps.fWordsMap.push_back({word_start, i - word_start, word_advance, word_ascent});
            }
        }

        if (!frag.fIsWhitespace) {
            fMaps.fNonWhitespaceMap.push_back({i, 1, 0, 0});

            if (!in_word) {
                in_word = true;
                word_start = i;
                word_advance = word_ascent = 0;
            }

            word_advance += frag.fAdvance;
            word_ascent   = std::min(word_ascent, frag.fAscent); // negative ascent
        }

        if (is_new_line) {
            SkASSERT(frag.fLineIndex == line + 1);
            fMaps.fLinesMap.push_back({line_start, i - line_start, line_advance, line_ascent});
            line = frag.fLineIndex;
            line_start = i;
            line_advance = line_ascent = 0;
        }

        line_advance += frag.fAdvance;
        line_ascent   = std::min(line_ascent, frag.fAscent); // negative ascent
    }

    if (i > word_start) {
        fMaps.fWordsMap.push_back({word_start, i - word_start, word_advance, word_ascent});
    }

    if (i > line_start) {
        fMaps.fLinesMap.push_back({line_start, i - line_start, line_advance, line_ascent});
    }

    for (auto& animator : fAnimators) {
        animator->updateDomainMaps(fMaps, shape_result.fFragments.size());
    }
}

void TextAdapter::setText(const TextValue& txt) {
    fText.fCurrentValue = txt;
    this->onSync();
}

uint32_t TextAdapter::shaperFlags() const {
    uint32_t flags = Shaper::Flags::kNone;

    // We need granular fragments (as opposed to consolidated blobs):
    //   - when animating
    //   - when positioning on a path
    //   - when clamping the number or lines (for accurate line count)
    //   - when a text decorator is present
    if (!fAnimators.empty() || fPathInfo || fText->fMaxLines || fText->fDecorator) {
        flags |= Shaper::Flags::kFragmentGlyphs;
    }

    if (fRequiresAnchorPoint || fText->fDecorator) {
        flags |= Shaper::Flags::kTrackFragmentAdvanceAscent;
    }

    if (fText->fDecorator) {
        flags |= Shaper::Flags::kClusters;
    }

    return flags;
}

void TextAdapter::reshape() {
    // AE clamps the font size to a reasonable range.
    // We do the same, since HB is susceptible to int overflows for degenerate values.
    static constexpr float kMinSize =    0.1f,
                           kMaxSize = 1296.0f;
    const Shaper::TextDesc text_desc = {
        fText->fTypeface,
        SkTPin(fText->fTextSize,    kMinSize, kMaxSize),
        SkTPin(fText->fMinTextSize, kMinSize, kMaxSize),
        SkTPin(fText->fMaxTextSize, kMinSize, kMaxSize),
        fText->fLineHeight,
        fText->fLineShift,
        fText->fAscent,
        fText->fHAlign,
        fText->fVAlign,
        fText->fResize,
        fText->fLineBreak,
        fText->fDirection,
        fText->fCapitalization,
        fText->fMaxLines,
        this->shaperFlags(),
        fText->fLocale.isEmpty()     ? nullptr : fText->fLocale.c_str(),
        fText->fFontFamily.isEmpty() ? nullptr : fText->fFontFamily.c_str(),
        fText->fTextTracking,
    };
    auto shape_result = Shaper::Shape(fText->fText, text_desc, fText->fBox, fFontMgr,
        fShapingFactory);

    if (fLogger) {
        if (shape_result.fFragments.empty() && fText->fText.size() > 0) {
            const auto msg = SkStringPrintf("Text layout failed for '%s'.",
                                            fText->fText.c_str());
            fLogger->log(Logger::Level::kError, msg.c_str());

            // These may trigger repeatedly when the text is animating.
            // To avoid spamming, only log once.
            fLogger = nullptr;
        }

        if (shape_result.fMissingGlyphCount > 0) {
            const auto msg = SkStringPrintf("Missing %zu glyphs for '%s'.",
                                            shape_result.fMissingGlyphCount,
                                            fText->fText.c_str());
            fLogger->log(Logger::Level::kWarning, msg.c_str());
            fLogger = nullptr;
        }
    }

    // Save the text shaping scale for later adjustments.
    fTextShapingScale = shape_result.fScale;

    // Rebuild all fragments.
    // TODO: we can be smarter here and try to reuse the existing SG structure if needed.

    fRoot->clear();
    fFragments.clear();

    if (SHOW_LAYOUT_BOXES) {
        auto box_color = sksg::Color::Make(0xffff0000);
        box_color->setStyle(SkPaint::kStroke_Style);
        box_color->setStrokeWidth(1);
        box_color->setAntiAlias(true);

        auto bounds_color = sksg::Color::Make(0xff00ff00);
        bounds_color->setStyle(SkPaint::kStroke_Style);
        bounds_color->setStrokeWidth(1);
        bounds_color->setAntiAlias(true);

        fRoot->addChild(sksg::Draw::Make(sksg::Rect::Make(fText->fBox),
                                         std::move(box_color)));
        fRoot->addChild(sksg::Draw::Make(sksg::Rect::Make(shape_result.computeVisualBounds()),
                                         std::move(bounds_color)));

        if (fPathInfo) {
            auto path_color = sksg::Color::Make(0xffffff00);
            path_color->setStyle(SkPaint::kStroke_Style);
            path_color->setStrokeWidth(1);
            path_color->setAntiAlias(true);

            fRoot->addChild(
                        sksg::Draw::Make(sksg::Path::Make(static_cast<SkPath>(fPathInfo->fPath)),
                                         std::move(path_color)));
        }
    }

    // Depending on whether a GlyphDecorator is present, we either add the glyph render nodes
    // directly to the root group, or to an intermediate GlyphDecoratorNode container.
    sksg::Group* container = fRoot.get();
    sk_sp<GlyphDecoratorNode> decorator_node;
    if (fText->fDecorator) {
        decorator_node = sk_make_sp<GlyphDecoratorNode>(fText->fDecorator, fTextShapingScale);
        container = decorator_node.get();
    }

    // N.B. addFragment moves shaped glyph data out of the fragment, so only the fragment
    // metrics are valid after this block.
    for (size_t i = 0; i < shape_result.fFragments.size(); ++i) {
        this->addFragment(shape_result.fFragments[i], container);
    }

    if (decorator_node) {
        decorator_node->updateFragmentData(fFragments);
        fRoot->addChild(std::move(decorator_node));
    }

    if (!fAnimators.empty() || fPathInfo) {
        // Range selectors and text paths require fragment domain maps.
        this->buildDomainMaps(shape_result);
    }
}

void TextAdapter::onSync() {
    if (!fText->fHasFill && !fText->fHasStroke) {
        return;
    }

    if (fText.hasChanged()) {
        this->reshape();
    }

    if (fFragments.empty()) {
        return;
    }

    // Update the path contour measure, if needed.
    if (fPathInfo) {
        fPathInfo->updateContourData();
    }

    // Seed props from the current text value.
    TextAnimator::ResolvedProps seed_props;
    seed_props.fill_color   = fText->fFillColor;
    seed_props.stroke_color = fText->fStrokeColor;
    seed_props.stroke_width = fText->fStrokeWidth;

    TextAnimator::ModulatorBuffer buf;
    buf.resize(fFragments.size(), { seed_props, 0 });

    // Apply all animators to the modulator buffer.
    for (const auto& animator : fAnimators) {
        animator->modulateProps(buf);
    }

    const TextAnimator::DomainMap* grouping_domain = nullptr;
    switch (fAnchorPointGrouping) {
        // for word/line grouping, we rely on domain map info
        case AnchorPointGrouping::kWord: grouping_domain = &fMaps.fWordsMap; break;
        case AnchorPointGrouping::kLine: grouping_domain = &fMaps.fLinesMap; break;
        // remaining grouping modes (character/all) do not need (or have) domain map data
        default: break;
    }

    size_t grouping_span_index = 0;
    SkV2   current_line_offset = { 0, 0 }; // cumulative line spacing

    auto compute_linewide_props = [this](const TextAnimator::ModulatorBuffer& buf,
                                         const TextAnimator::DomainSpan& line_span) {
        SkV2  total_spacing  = {0,0};
        float total_tracking = 0;

        // Only compute these when needed.
        if (fRequiresLineAdjustments && line_span.fCount) {
            for (size_t i = line_span.fOffset; i < line_span.fOffset + line_span.fCount; ++i) {
                const auto& props = buf[i].props;
                total_spacing  += props.line_spacing;
                total_tracking += props.tracking;
            }

            // The first glyph does not contribute |before| tracking, and the last one does not
            // contribute |after| tracking.
            total_tracking -= 0.5f * (buf[line_span.fOffset].props.tracking +
                                      buf[line_span.fOffset + line_span.fCount - 1].props.tracking);
        }

        return std::make_tuple(total_spacing, total_tracking);
    };

    // Finally, push all props to their corresponding fragment.
    for (const auto& line_span : fMaps.fLinesMap) {
        const auto [line_spacing, line_tracking] = compute_linewide_props(buf, line_span);
        const auto align_offset = -line_tracking * align_factor(fText->fHAlign);

        // line spacing of the first line is ignored (nothing to "space" against)
        if (&line_span != &fMaps.fLinesMap.front() && line_span.fCount) {
            // For each line, the actual spacing is an average of individual fragment spacing
            // (to preserve the "line").
            current_line_offset += line_spacing / line_span.fCount;
        }

        float tracking_acc = 0;
        for (size_t i = line_span.fOffset; i < line_span.fOffset + line_span.fCount; ++i) {
            // Track the grouping domain span in parallel.
            if (grouping_domain && i >= (*grouping_domain)[grouping_span_index].fOffset +
                                        (*grouping_domain)[grouping_span_index].fCount) {
                grouping_span_index += 1;
                SkASSERT(i < (*grouping_domain)[grouping_span_index].fOffset +
                             (*grouping_domain)[grouping_span_index].fCount);
            }

            const auto& props = buf[i].props;
            const auto& frag  = fFragments[i];

            // AE tracking is defined per glyph, based on two components: |before| and |after|.
            // BodyMovin only exports "balanced" tracking values, where before = after = tracking/2.
            //
            // Tracking is applied as a local glyph offset, and contributes to the line width for
            // alignment purposes.
            //
            // No |before| tracking for the first glyph, nor |after| tracking for the last one.
            const auto track_before = i > line_span.fOffset
                                        ? props.tracking * 0.5f : 0.0f,
                       track_after  = i < line_span.fOffset + line_span.fCount - 1
                                        ? props.tracking * 0.5f : 0.0f;

            const auto frag_offset = current_line_offset +
                                     SkV2{align_offset + tracking_acc + track_before, 0};

            tracking_acc += track_before + track_after;

            this->pushPropsToFragment(props, frag, frag_offset, fGroupingAlignment * .01f, // %
                                      grouping_domain ? &(*grouping_domain)[grouping_span_index]
                                                        : nullptr);
        }
    }
}

SkV2 TextAdapter::fragmentAnchorPoint(const FragmentRec& rec,
                                      const SkV2& grouping_alignment,
                                      const TextAnimator::DomainSpan* grouping_span) const {
    // Construct the following 2x ascent box:
    //
    //      -------------
    //     |             |
    //     |             | ascent
    //     |             |
    // ----+-------------+---------- baseline
    //   (pos)           |
    //     |             | ascent
    //     |             |
    //      -------------
    //         advance

    auto make_box = [](const SkPoint& pos, float advance, float ascent) {
        // note: negative ascent
        return SkRect::MakeXYWH(pos.fX, pos.fY + ascent, advance, -2 * ascent);
    };

    // Compute a grouping-dependent anchor point box.
    // The default anchor point is at the center, and gets adjusted relative to the bounds
    // based on |grouping_alignment|.
    auto anchor_box = [&]() -> SkRect {
        switch (fAnchorPointGrouping) {
        case AnchorPointGrouping::kCharacter:
            // Anchor box relative to each individual fragment.
            return make_box(rec.fOrigin, rec.fAdvance, rec.fAscent);
        case AnchorPointGrouping::kWord:
            // Fall through
        case AnchorPointGrouping::kLine: {
            SkASSERT(grouping_span);
            // Anchor box relative to the first fragment in the word/line.
            const auto& first_span_fragment = fFragments[grouping_span->fOffset];
            return make_box(first_span_fragment.fOrigin,
                            grouping_span->fAdvance,
                            grouping_span->fAscent);
        }
        case AnchorPointGrouping::kAll:
            // Anchor box is the same as the text box.
            return fText->fBox;
        }
        SkUNREACHABLE;
    };

    const auto ab = anchor_box();

    // Apply grouping alignment.
    const auto ap = SkV2 { ab.centerX() + ab.width()  * 0.5f * grouping_alignment.x,
                           ab.centerY() + ab.height() * 0.5f * grouping_alignment.y };

    // The anchor point is relative to the fragment position.
    return ap - SkV2 { rec.fOrigin.fX, rec.fOrigin.fY };
}

SkM44 TextAdapter::fragmentMatrix(const TextAnimator::ResolvedProps& props,
                                  const FragmentRec& rec, const SkV2& frag_offset) const {
    const SkV3 pos = {
        props.position.x + rec.fOrigin.fX + frag_offset.x,
        props.position.y + rec.fOrigin.fY + frag_offset.y,
        props.position.z
    };

    if (!fPathInfo) {
        return SkM44::Translate(pos.x, pos.y, pos.z);
    }

    // "Align" the paragraph box left/center/right to path start/mid/end, respectively.
    const auto align_offset =
            align_factor(fText->fHAlign)*(fPathInfo->pathLength() - fText->fBox.width());

    // Path positioning is based on the fragment position relative to the paragraph box
    // upper-left corner:
    //
    //   - the horizontal component determines the distance on path
    //
    //   - the vertical component is post-applied after orienting on path
    //
    // Note: in point-text mode, the box adjustments have no effect as fBox is {0,0,0,0}.
    //
    const auto rel_pos = SkV2{pos.x, pos.y} - SkV2{fText->fBox.fLeft, fText->fBox.fTop};
    const auto path_distance = rel_pos.x + align_offset;

    return fPathInfo->getMatrix(path_distance, fText->fHAlign)
         * SkM44::Translate(0, rel_pos.y, pos.z);
}

void TextAdapter::pushPropsToFragment(const TextAnimator::ResolvedProps& props,
                                      const FragmentRec& rec,
                                      const SkV2& frag_offset,
                                      const SkV2& grouping_alignment,
                                      const TextAnimator::DomainSpan* grouping_span) const {
    const auto anchor_point = this->fragmentAnchorPoint(rec, grouping_alignment, grouping_span);

    rec.fMatrixNode->setMatrix(
                this->fragmentMatrix(props, rec, anchor_point + frag_offset)
              * SkM44::Rotate({ 1, 0, 0 }, SkDegreesToRadians(props.rotation.x))
              * SkM44::Rotate({ 0, 1, 0 }, SkDegreesToRadians(props.rotation.y))
              * SkM44::Rotate({ 0, 0, 1 }, SkDegreesToRadians(props.rotation.z))
              * SkM44::Scale(props.scale.x, props.scale.y, props.scale.z)
              * SkM44::Translate(-anchor_point.x, -anchor_point.y, 0));

    const auto scale_alpha = [](SkColor c, float o) {
        return SkColorSetA(c, SkScalarRoundToInt(o * SkColorGetA(c)));
    };

    if (rec.fFillColorNode) {
        rec.fFillColorNode->setColor(scale_alpha(props.fill_color, props.opacity));
    }
    if (rec.fStrokeColorNode) {
        rec.fStrokeColorNode->setColor(scale_alpha(props.stroke_color, props.opacity));
        rec.fStrokeColorNode->setStrokeWidth(props.stroke_width * fTextShapingScale);
    }
    if (rec.fBlur) {
        rec.fBlur->setSigma({ props.blur.x * kBlurSizeToSigma,
                              props.blur.y * kBlurSizeToSigma });
    }
}

} // namespace skottie::internal
