/*
 * Copyright 2019 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "modules/svg/include/SkSVGText.h"

#include "include/core/SkCanvas.h"
#include "include/core/SkContourMeasure.h"
#include "include/core/SkFont.h"
#include "include/core/SkFontMgr.h"
#include "include/core/SkFontStyle.h"
#include "include/core/SkFontTypes.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPathBuilder.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRSXform.h"
#include "include/core/SkScalar.h"
#include "include/core/SkString.h"
#include "include/core/SkTextBlob.h"
#include "include/core/SkTypeface.h"
#include "include/core/SkTypes.h"
#include "include/private/base/SkTArray.h"
#include "include/private/base/SkTemplates.h"
#include "include/private/base/SkTo.h"
#include "modules/skshaper/include/SkShaper.h"
#include "modules/svg/include/SkSVGAttribute.h"
#include "modules/svg/include/SkSVGAttributeParser.h"
#include "modules/svg/include/SkSVGRenderContext.h"
#include "modules/svg/src/SkSVGTextPriv.h"
#include "src/base/SkUTF.h"
#include "src/core/SkTextBlobPriv.h"

#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <limits>
#include <memory>
#include <tuple>
#include <utility>

using namespace skia_private;

namespace {

static SkFont ResolveFont(const SkSVGRenderContext& ctx) {
    auto weight = [](const SkSVGFontWeight& w) {
        switch (w.type()) {
            case SkSVGFontWeight::Type::k100:     return SkFontStyle::kThin_Weight;
            case SkSVGFontWeight::Type::k200:     return SkFontStyle::kExtraLight_Weight;
            case SkSVGFontWeight::Type::k300:     return SkFontStyle::kLight_Weight;
            case SkSVGFontWeight::Type::k400:     return SkFontStyle::kNormal_Weight;
            case SkSVGFontWeight::Type::k500:     return SkFontStyle::kMedium_Weight;
            case SkSVGFontWeight::Type::k600:     return SkFontStyle::kSemiBold_Weight;
            case SkSVGFontWeight::Type::k700:     return SkFontStyle::kBold_Weight;
            case SkSVGFontWeight::Type::k800:     return SkFontStyle::kExtraBold_Weight;
            case SkSVGFontWeight::Type::k900:     return SkFontStyle::kBlack_Weight;
            case SkSVGFontWeight::Type::kNormal:  return SkFontStyle::kNormal_Weight;
            case SkSVGFontWeight::Type::kBold:    return SkFontStyle::kBold_Weight;
            case SkSVGFontWeight::Type::kBolder:  return SkFontStyle::kExtraBold_Weight;
            case SkSVGFontWeight::Type::kLighter: return SkFontStyle::kLight_Weight;
            case SkSVGFontWeight::Type::kInherit: {
                SkASSERT(false);
                return SkFontStyle::kNormal_Weight;
            }
        }
        SkUNREACHABLE;
    };

    auto slant = [](const SkSVGFontStyle& s) {
        switch (s.type()) {
            case SkSVGFontStyle::Type::kNormal:  return SkFontStyle::kUpright_Slant;
            case SkSVGFontStyle::Type::kItalic:  return SkFontStyle::kItalic_Slant;
            case SkSVGFontStyle::Type::kOblique: return SkFontStyle::kOblique_Slant;
            case SkSVGFontStyle::Type::kInherit: {
                SkASSERT(false);
                return SkFontStyle::kUpright_Slant;
            }
        }
        SkUNREACHABLE;
    };

    const auto& family = ctx.presentationContext().fInherited.fFontFamily->family();
    const SkFontStyle style(weight(*ctx.presentationContext().fInherited.fFontWeight),
                            SkFontStyle::kNormal_Width,
                            slant(*ctx.presentationContext().fInherited.fFontStyle));

    const auto size =
            ctx.lengthContext().resolve(ctx.presentationContext().fInherited.fFontSize->size(),
                                        SkSVGLengthContext::LengthType::kVertical);

    // TODO: we likely want matchFamilyStyle here, but switching away from legacyMakeTypeface
    // changes all the results when using the default fontmgr.
    auto tf = ctx.fontMgr()->legacyMakeTypeface(family.c_str(), style);
    if (!tf) {
        tf = ctx.fontMgr()->legacyMakeTypeface(nullptr, style);
    }
    SkASSERT(tf);
    SkFont font(std::move(tf), size);
    font.setHinting(SkFontHinting::kNone);
    font.setSubpixel(true);
    font.setLinearMetrics(true);
    font.setBaselineSnap(false);
    font.setEdging(SkFont::Edging::kAntiAlias);

    return font;
}

static std::vector<float> ResolveLengths(const SkSVGLengthContext& lctx,
                                         const std::vector<SkSVGLength>& lengths,
                                         SkSVGLengthContext::LengthType lt) {
    std::vector<float> resolved;
    resolved.reserve(lengths.size());

    for (const auto& l : lengths) {
        resolved.push_back(lctx.resolve(l, lt));
    }

    return resolved;
}

static float ComputeAlignmentFactor(const SkSVGPresentationContext& pctx) {
    switch (pctx.fInherited.fTextAnchor->type()) {
    case SkSVGTextAnchor::Type::kStart : return  0.0f;
    case SkSVGTextAnchor::Type::kMiddle: return -0.5f;
    case SkSVGTextAnchor::Type::kEnd   : return -1.0f;
    case SkSVGTextAnchor::Type::kInherit:
        SkASSERT(false);
        return 0.0f;
    }
    SkUNREACHABLE;
}

} // namespace

SkSVGTextContext::ScopedPosResolver::ScopedPosResolver(const SkSVGTextContainer& txt,
                                                       const SkSVGLengthContext& lctx,
                                                       SkSVGTextContext* tctx,
                                                       size_t charIndexOffset)
    : fTextContext(tctx)
    , fParent(tctx->fPosResolver)
    , fCharIndexOffset(charIndexOffset)
    , fX(ResolveLengths(lctx, txt.getX(), SkSVGLengthContext::LengthType::kHorizontal))
    , fY(ResolveLengths(lctx, txt.getY(), SkSVGLengthContext::LengthType::kVertical))
    , fDx(ResolveLengths(lctx, txt.getDx(), SkSVGLengthContext::LengthType::kHorizontal))
    , fDy(ResolveLengths(lctx, txt.getDy(), SkSVGLengthContext::LengthType::kVertical))
    , fRotate(txt.getRotate())
{
    fTextContext->fPosResolver = this;
}

SkSVGTextContext::ScopedPosResolver::ScopedPosResolver(const SkSVGTextContainer& txt,
                                                       const SkSVGLengthContext& lctx,
                                                       SkSVGTextContext* tctx)
    : ScopedPosResolver(txt, lctx, tctx, tctx->fCurrentCharIndex) {}

SkSVGTextContext::ScopedPosResolver::~ScopedPosResolver() {
    fTextContext->fPosResolver = fParent;
}

SkSVGTextContext::PosAttrs SkSVGTextContext::ScopedPosResolver::resolve(size_t charIndex) const {
    PosAttrs attrs;

    if (charIndex < fLastPosIndex) {
        SkASSERT(charIndex >= fCharIndexOffset);
        const auto localCharIndex = charIndex - fCharIndexOffset;

        const auto hasAllLocal = localCharIndex < fX.size() &&
                                 localCharIndex < fY.size() &&
                                 localCharIndex < fDx.size() &&
                                 localCharIndex < fDy.size() &&
                                 localCharIndex < fRotate.size();
        if (!hasAllLocal && fParent) {
            attrs = fParent->resolve(charIndex);
        }

        if (localCharIndex < fX.size()) {
            attrs[PosAttrs::kX] = fX[localCharIndex];
        }
        if (localCharIndex < fY.size()) {
            attrs[PosAttrs::kY] = fY[localCharIndex];
        }
        if (localCharIndex < fDx.size()) {
            attrs[PosAttrs::kDx] = fDx[localCharIndex];
        }
        if (localCharIndex < fDy.size()) {
            attrs[PosAttrs::kDy] = fDy[localCharIndex];
        }

        // Rotation semantics are interestingly different [1]:
        //
        //   - values are not cumulative
        //   - if explicit values are present at any level in the ancestor chain, those take
        //     precedence (closest ancestor)
        //   - last specified value applies to all remaining chars (closest ancestor)
        //   - these rules apply at node scope (not chunk scope)
        //
        // This means we need to discriminate between explicit rotation (rotate value provided for
        // current char) and implicit rotation (ancestor has some values - but not for the requested
        // char - we use the last specified value).
        //
        // [1] https://www.w3.org/TR/SVG11/text.html#TSpanElementRotateAttribute
        if (!fRotate.empty()) {
            if (localCharIndex < fRotate.size()) {
                // Explicit rotation value overrides anything in the ancestor chain.
                attrs[PosAttrs::kRotate] = fRotate[localCharIndex];
                attrs.setImplicitRotate(false);
            } else if (!attrs.has(PosAttrs::kRotate) || attrs.isImplicitRotate()){
                // Local implicit rotation (last specified value) overrides ancestor implicit
                // rotation.
                attrs[PosAttrs::kRotate] = fRotate.back();
                attrs.setImplicitRotate(true);
            }
        }

        if (!attrs.hasAny()) {
            // Once we stop producing explicit position data, there is no reason to
            // continue trying for higher indices.  We can suppress future lookups.
            fLastPosIndex = charIndex;
        }
    }

    return attrs;
}

void SkSVGTextContext::ShapeBuffer::append(SkUnichar ch, PositionAdjustment pos) {
    // relative pos adjustments are cumulative
    if (!fUtf8PosAdjust.empty()) {
        pos.offset += fUtf8PosAdjust.back().offset;
    }

    char utf8_buf[SkUTF::kMaxBytesInUTF8Sequence];
    const auto utf8_len = SkToInt(SkUTF::ToUTF8(ch, utf8_buf));
    fUtf8         .push_back_n(utf8_len, utf8_buf);
    fUtf8PosAdjust.push_back_n(utf8_len, pos);
}

void SkSVGTextContext::shapePendingBuffer(const SkSVGRenderContext& ctx, const SkFont& font) {
    const char* utf8 = fShapeBuffer.fUtf8.data();
    size_t utf8Bytes = fShapeBuffer.fUtf8.size();

    std::unique_ptr<SkShaper::FontRunIterator> font_runs =
            SkShaper::MakeFontMgrRunIterator(utf8, utf8Bytes, font, ctx.fontMgr());
    if (!font_runs) {
        return;
    }
    if (!fForcePrimitiveShaping) {
        // Try to use the passed in shaping callbacks to shape, for example, using harfbuzz and ICU.
        const uint8_t defaultLTR = 0;
        std::unique_ptr<SkShaper::BiDiRunIterator> bidi =
                ctx.makeBidiRunIterator(utf8, utf8Bytes, defaultLTR);
        std::unique_ptr<SkShaper::LanguageRunIterator> language =
                SkShaper::MakeStdLanguageRunIterator(utf8, utf8Bytes);
        std::unique_ptr<SkShaper::ScriptRunIterator> script = ctx.makeScriptRunIterator(utf8, utf8Bytes);

        if (bidi && script && language) {
            fShaper->shape(utf8,
                           utf8Bytes,
                           *font_runs,
                           *bidi,
                           *script,
                           *language,
                           nullptr,
                           0,
                           SK_ScalarMax,
                           this);
            fShapeBuffer.reset();
            return;
        }  // If any of the callbacks fail, we'll fallback to the primitive shaping.
    }

    // bidi, script, and lang are all unused so we can construct them with empty data.
    SkShaper::TrivialBiDiRunIterator trivial_bidi{0, 0};
    SkShaper::TrivialScriptRunIterator trivial_script{0, 0};
    SkShaper::TrivialLanguageRunIterator trivial_lang{nullptr, 0};
    fShaper->shape(utf8,
                   utf8Bytes,
                   *font_runs,
                   trivial_bidi,
                   trivial_script,
                   trivial_lang,
                   nullptr,
                   0,
                   SK_ScalarMax,
                   this);
    fShapeBuffer.reset();
}

SkSVGTextContext::SkSVGTextContext(const SkSVGRenderContext& ctx,
                                   const ShapedTextCallback& cb,
                                   const SkSVGTextPath* tpath)
        : fRenderContext(ctx)
        , fCallback(cb)
        , fShaper(ctx.makeShaper())
        , fChunkAlignmentFactor(ComputeAlignmentFactor(ctx.presentationContext())) {
    // If the shaper callback returns null, fallback to the primitive shaper and
    // signal that we should not use the other callbacks in shapePendingBuffer
    if (!fShaper) {
        fShaper = SkShapers::Primitive::PrimitiveText();
        fForcePrimitiveShaping = true;
    }
    if (tpath) {
        fPathData = std::make_unique<PathData>(ctx, *tpath);

        // https://www.w3.org/TR/SVG11/text.html#TextPathElementStartOffsetAttribute
        auto resolve_offset = [this](const SkSVGLength& offset) {
            if (offset.unit() != SkSVGLength::Unit::kPercentage) {
                // "If a <length> other than a percentage is given, then the ‘startOffset’
                // represents a distance along the path measured in the current user coordinate
                // system."
                return fRenderContext.lengthContext()
                                     .resolve(offset, SkSVGLengthContext::LengthType::kHorizontal);
            }

            // "If a percentage is given, then the ‘startOffset’ represents a percentage distance
            // along the entire path."
            return offset.value() * fPathData->length() / 100;
        };

        // startOffset acts as an initial absolute position
        fChunkPos.fX = resolve_offset(tpath->getStartOffset());
    }
}

SkSVGTextContext::~SkSVGTextContext() {
    this->flushChunk(fRenderContext);
}

void SkSVGTextContext::shapeFragment(const SkString& txt, const SkSVGRenderContext& ctx,
                                     SkSVGXmlSpace xs) {
    // https://www.w3.org/TR/SVG11/text.html#WhiteSpace
    // https://www.w3.org/TR/2008/REC-xml-20081126/#NT-S
    auto filterWSDefault = [this](SkUnichar ch) -> SkUnichar {
        // Remove all newline chars.
        if (ch == '\n') {
            return -1;
        }

        // Convert tab chars to space.
        if (ch == '\t') {
            ch = ' ';
        }

        // Consolidate contiguous space chars and strip leading spaces (fPrevCharSpace
        // starts off as true).
        if (fPrevCharSpace && ch == ' ') {
            return -1;
        }

        // TODO: Strip trailing WS?  Doing this across chunks would require another buffering
        //   layer.  In general, trailing WS should have no rendering side effects. Skipping
        //   for now.
        return ch;
    };
    auto filterWSPreserve = [](SkUnichar ch) -> SkUnichar {
        // Convert newline and tab chars to space.
        if (ch == '\n' || ch == '\t') {
            ch = ' ';
        }
        return ch;
    };

    // Stash paints for access from SkShaper callbacks.
    fCurrentFill   = ctx.fillPaint();
    fCurrentStroke = ctx.strokePaint();

    const auto font = ResolveFont(ctx);
    fShapeBuffer.reserve(txt.size());

    const char* ch_ptr = txt.c_str();
    const char* ch_end = ch_ptr + txt.size();

    while (ch_ptr < ch_end) {
        auto ch = SkUTF::NextUTF8(&ch_ptr, ch_end);
        ch = (xs == SkSVGXmlSpace::kDefault)
                ? filterWSDefault(ch)
                : filterWSPreserve(ch);

        if (ch < 0) {
            // invalid utf or char filtered out
            continue;
        }

        SkASSERT(fPosResolver);
        const auto pos = fPosResolver->resolve(fCurrentCharIndex++);

        // Absolute position adjustments define a new chunk.
        // (https://www.w3.org/TR/SVG11/text.html#TextLayoutIntroduction)
        if (pos.has(PosAttrs::kX) || pos.has(PosAttrs::kY)) {
            this->shapePendingBuffer(ctx, font);
            this->flushChunk(ctx);

            // New chunk position.
            if (pos.has(PosAttrs::kX)) {
                fChunkPos.fX = pos[PosAttrs::kX];
            }
            if (pos.has(PosAttrs::kY)) {
                fChunkPos.fY = pos[PosAttrs::kY];
            }
        }

        fShapeBuffer.append(ch, {
            {
                pos.has(PosAttrs::kDx) ? pos[PosAttrs::kDx] : 0,
                pos.has(PosAttrs::kDy) ? pos[PosAttrs::kDy] : 0,
            },
            pos.has(PosAttrs::kRotate) ? SkDegreesToRadians(pos[PosAttrs::kRotate]) : 0,
        });

        fPrevCharSpace = (ch == ' ');
    }

    this->shapePendingBuffer(ctx, font);

    // Note: at this point we have shaped and buffered RunRecs for the current fragment.
    // The active text chunk continues until an explicit or implicit flush.
}

SkSVGTextContext::PathData::PathData(const SkSVGRenderContext& ctx, const SkSVGTextPath& tpath)
{
    const auto ref = ctx.findNodeById(tpath.getHref());
    if (!ref) {
        return;
    }

    SkContourMeasureIter cmi(ref->asPath(ctx), false);
    while (sk_sp<SkContourMeasure> contour = cmi.next()) {
        fLength += contour->length();
        fContours.push_back(std::move(contour));
    }
}

SkMatrix SkSVGTextContext::PathData::getMatrixAt(float offset) const {
    if (offset >= 0) {
        for (const auto& contour : fContours) {
            const auto contour_len = contour->length();
            if (offset < contour_len) {
                SkMatrix m;
                return contour->getMatrix(offset, &m) ? m : SkMatrix::I();
            }
            offset -= contour_len;
        }
    }

    // Quick & dirty way to "skip" rendering of glyphs off path.
    return SkMatrix::Translate(std::numeric_limits<float>::infinity(),
                               std::numeric_limits<float>::infinity());
}

SkRSXform SkSVGTextContext::computeGlyphXform(SkGlyphID glyph, const SkFont& font,
                                              const SkPoint& glyph_pos,
                                              const PositionAdjustment& pos_adjust) const {
    SkPoint pos = fChunkPos + glyph_pos + pos_adjust.offset + fChunkAdvance * fChunkAlignmentFactor;
    if (!fPathData) {
        return SkRSXform::MakeFromRadians(/*scale=*/ 1, pos_adjust.rotation, pos.fX, pos.fY, 0, 0);
    }

    // We're in a textPath scope, reposition the glyph on path.
    // (https://www.w3.org/TR/SVG11/text.html#TextpathLayoutRules)

    // Path positioning is based on the glyph center (horizontal component).
    float glyph_width = font.getWidth(glyph);
    auto path_offset = pos.fX + glyph_width * .5f;

    // In addition to the path matrix, the final glyph matrix also includes:
    //
    //   -- vertical position adjustment "dy" ("dx" is factored into path_offset)
    //   -- glyph origin adjustment (undoing the glyph center offset above)
    //   -- explicit rotation adjustment (composing with the path glyph rotation)
    const auto m = fPathData->getMatrixAt(path_offset) *
            SkMatrix::Translate(-glyph_width * .5f, pos_adjust.offset.fY) *
            SkMatrix::RotateRad(pos_adjust.rotation);

    return SkRSXform::Make(m.getScaleX(), m.getSkewY(), m.getTranslateX(), m.getTranslateY());
}

void SkSVGTextContext::flushChunk(const SkSVGRenderContext& ctx) {
    SkTextBlobBuilder blobBuilder;

    for (const auto& run : fRuns) {
        const auto& buf = blobBuilder.allocRunRSXform(run.font, SkToInt(run.glyphCount));
        std::copy(run.glyphs.get(), run.glyphs.get() + run.glyphCount, buf.glyphs);
        for (size_t i = 0; i < run.glyphCount; ++i) {
            buf.xforms()[i] = this->computeGlyphXform(run.glyphs[i],
                                                      run.font,
                                                      run.glyphPos[i],
                                                      run.glyhPosAdjust[i]);
        }

        fCallback(ctx, blobBuilder.make(), run.fillPaint.get(), run.strokePaint.get());
    }

    fChunkPos += fChunkAdvance;
    fChunkAdvance = {0,0};
    fChunkAlignmentFactor = ComputeAlignmentFactor(ctx.presentationContext());

    fRuns.clear();
}

SkShaper::RunHandler::Buffer SkSVGTextContext::runBuffer(const RunInfo& ri) {
    SkASSERT(ri.glyphCount);

    fRuns.push_back({
        ri.fFont,
        fCurrentFill.has_value()   ? std::make_unique<SkPaint>(*fCurrentFill)   : nullptr,
        fCurrentStroke.has_value() ? std::make_unique<SkPaint>(*fCurrentStroke) : nullptr,
        std::make_unique<SkGlyphID[]         >(ri.glyphCount),
        std::make_unique<SkPoint[]           >(ri.glyphCount),
        std::make_unique<PositionAdjustment[]>(ri.glyphCount),
        ri.glyphCount,
        ri.fAdvance,
    });

    // Ensure sufficient space to temporarily fetch cluster information.
    fShapeClusterBuffer.resize(std::max(fShapeClusterBuffer.size(), ri.glyphCount));

    return {
        fRuns.back().glyphs.get(),
        fRuns.back().glyphPos.get(),
        nullptr,
        fShapeClusterBuffer.data(),
        fChunkAdvance,
    };
}

void SkSVGTextContext::commitRunBuffer(const RunInfo& ri) {
    const auto& current_run = fRuns.back();

    // stash position adjustments
    for (size_t i = 0; i < ri.glyphCount; ++i) {
        const auto utf8_index = fShapeClusterBuffer[i];
        current_run.glyhPosAdjust[i] = fShapeBuffer.fUtf8PosAdjust[SkToInt(utf8_index)];
    }

    fChunkAdvance += ri.fAdvance;
}

void SkSVGTextContext::commitLine() {
    if (!fShapeBuffer.fUtf8PosAdjust.empty()) {
        // Offset adjustments are cumulative - only advance the current chunk with the last value.
        fChunkAdvance += fShapeBuffer.fUtf8PosAdjust.back().offset;
    }
}

void SkSVGTextFragment::renderText(const SkSVGRenderContext& ctx, SkSVGTextContext* tctx,
                                   SkSVGXmlSpace xs) const {
    // N.B.: unlike regular elements, text fragments do not establish a new OBB scope -- they
    // always defer to the root <text> element for OBB resolution.
    SkSVGRenderContext localContext(ctx);

    if (this->onPrepareToRender(&localContext)) {
        this->onShapeText(localContext, tctx, xs);
    }
}

SkPath SkSVGTextFragment::onAsPath(const SkSVGRenderContext&) const {
    // TODO
    return SkPath();
}

void SkSVGTextContainer::appendChild(sk_sp<SkSVGNode> child) {
    // Only allow text content child nodes.
    switch (child->tag()) {
    case SkSVGTag::kTextLiteral:
    case SkSVGTag::kTextPath:
    case SkSVGTag::kTSpan:
        fChildren.push_back(
            sk_sp<SkSVGTextFragment>(static_cast<SkSVGTextFragment*>(child.release())));
        break;
    default:
        break;
    }
}

void SkSVGTextContainer::onShapeText(const SkSVGRenderContext& ctx, SkSVGTextContext* tctx,
                                     SkSVGXmlSpace) const {
    SkASSERT(tctx);

    const SkSVGTextContext::ScopedPosResolver resolver(*this, ctx.lengthContext(), tctx);

    for (const auto& frag : fChildren) {
        // Containers always override xml:space with the local value.
        frag->renderText(ctx, tctx, this->getXmlSpace());
    }
}

// https://www.w3.org/TR/SVG11/text.html#WhiteSpace
template <>
bool SkSVGAttributeParser::parse(SkSVGXmlSpace* xs) {
    static constexpr std::tuple<const char*, SkSVGXmlSpace> gXmlSpaceMap[] = {
            {"default" , SkSVGXmlSpace::kDefault },
            {"preserve", SkSVGXmlSpace::kPreserve},
    };

    return this->parseEnumMap(gXmlSpaceMap, xs) && this->parseEOSToken();
}

bool SkSVGTextContainer::parseAndSetAttribute(const char* name, const char* value) {
    return INHERITED::parseAndSetAttribute(name, value) ||
           this->setX(SkSVGAttributeParser::parse<std::vector<SkSVGLength>>("x", name, value)) ||
           this->setY(SkSVGAttributeParser::parse<std::vector<SkSVGLength>>("y", name, value)) ||
           this->setDx(SkSVGAttributeParser::parse<std::vector<SkSVGLength>>("dx", name, value)) ||
           this->setDy(SkSVGAttributeParser::parse<std::vector<SkSVGLength>>("dy", name, value)) ||
           this->setRotate(SkSVGAttributeParser::parse<std::vector<SkSVGNumberType>>("rotate",
                                                                                     name,
                                                                                     value)) ||
           this->setXmlSpace(SkSVGAttributeParser::parse<SkSVGXmlSpace>("xml:space", name, value));
}

void SkSVGTextLiteral::onShapeText(const SkSVGRenderContext& ctx, SkSVGTextContext* tctx,
                                   SkSVGXmlSpace xs) const {
    SkASSERT(tctx);

    tctx->shapeFragment(this->getText(), ctx, xs);
}

void SkSVGText::onRender(const SkSVGRenderContext& ctx) const {
    const SkSVGTextContext::ShapedTextCallback render_text = [](const SkSVGRenderContext& ctx,
                                                                const sk_sp<SkTextBlob>& blob,
                                                                const SkPaint* fill,
                                                                const SkPaint* stroke) {
        if (fill) {
            ctx.canvas()->drawTextBlob(blob, 0, 0, *fill);
        }
        if (stroke) {
            ctx.canvas()->drawTextBlob(blob, 0, 0, *stroke);
        }
    };

    // Root <text> nodes establish a text layout context.
    SkSVGTextContext tctx(ctx, render_text);

    this->onShapeText(ctx, &tctx, this->getXmlSpace());
}

SkRect SkSVGText::onTransformableObjectBoundingBox(const SkSVGRenderContext& ctx) const {
    SkRect bounds = SkRect::MakeEmpty();

    const SkSVGTextContext::ShapedTextCallback compute_bounds =
        [&bounds](const SkSVGRenderContext& ctx, const sk_sp<SkTextBlob>& blob, const SkPaint*,
                  const SkPaint*) {
            if (!blob) {
                return;
            }

            AutoSTArray<64, SkRect> glyphBounds;

            for (SkTextBlobRunIterator it(blob.get()); !it.done(); it.next()) {
                const auto nglyphs = it.glyphCount();
                glyphBounds.reset(SkToInt(nglyphs));
                it.font().getBounds({it.glyphs(), nglyphs}, {glyphBounds.get(), nglyphs}, nullptr);

                SkASSERT(it.positioning() == SkTextBlobRunIterator::kRSXform_Positioning);
                SkMatrix m;
                for (uint32_t i = 0; i < it.glyphCount(); ++i) {
                    m.setRSXform(it.xforms()[i]);
                    bounds.join(m.mapRect(glyphBounds[i]));
                }
            }
        };

    {
        SkSVGTextContext tctx(ctx, compute_bounds);
        this->onShapeText(ctx, &tctx, this->getXmlSpace());
    }

    return bounds;
}

SkPath SkSVGText::onAsPath(const SkSVGRenderContext& ctx) const {
    SkPathBuilder builder;

    const SkSVGTextContext::ShapedTextCallback as_path =
        [&builder](const SkSVGRenderContext& ctx, const sk_sp<SkTextBlob>& blob, const SkPaint*,
                   const SkPaint*) {
            if (!blob) {
                return;
            }

            for (SkTextBlobRunIterator it(blob.get()); !it.done(); it.next()) {
                struct GetPathsCtx {
                    SkPathBuilder&   builder;
                    const SkRSXform* xform;
                } get_paths_ctx {builder, it.xforms()};

                it.font().getPaths({it.glyphs(), it.glyphCount()}, [](const SkPath* path,
                                                                      const SkMatrix& matrix,
                                                                      void* raw_ctx) {
                    auto* get_paths_ctx = static_cast<GetPathsCtx*>(raw_ctx);
                    const auto& glyph_rsx = *get_paths_ctx->xform++;

                    if (!path) {
                        return;
                    }

                    SkMatrix glyph_matrix;
                    glyph_matrix.setRSXform(glyph_rsx);
                    glyph_matrix.preConcat(matrix);

                    get_paths_ctx->builder.addPath(path->makeTransform(glyph_matrix));
                }, &get_paths_ctx);
            }
        };

    {
        SkSVGTextContext tctx(ctx, as_path);
        this->onShapeText(ctx, &tctx, this->getXmlSpace());
    }

    return this->mapToParent(builder.detach());
}

void SkSVGTextPath::onShapeText(const SkSVGRenderContext& ctx, SkSVGTextContext* parent_tctx,
                                 SkSVGXmlSpace xs) const {
    SkASSERT(parent_tctx);

    // textPath nodes establish a new text layout context.
    SkSVGTextContext tctx(ctx, parent_tctx->getCallback(), this);

    this->INHERITED::onShapeText(ctx, &tctx, xs);
}

bool SkSVGTextPath::parseAndSetAttribute(const char* name, const char* value) {
    return INHERITED::parseAndSetAttribute(name, value) ||
        this->setHref(SkSVGAttributeParser::parse<SkSVGIRI>("xlink:href", name, value)) ||
        this->setStartOffset(SkSVGAttributeParser::parse<SkSVGLength>("startOffset", name, value));
}
