/*
 * 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/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/SkTArray.h"
#include "include/private/SkTemplates.h"
#include "include/private/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/core/SkTextBlobPriv.h"
#include "src/core/SkUTF.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,
                           {},
                           {},
                           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,
                   {},
                   {},
                   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));
}
