/*
 * 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/include/TextShaper.h"

#include "include/core/SkCanvas.h"
#include "include/core/SkFontMetrics.h"
#include "include/core/SkFontMgr.h"
#include "include/core/SkFontTypes.h"
#include "include/core/SkFourByteTag.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/core/SkTypeface.h"
#include "include/core/SkTypes.h"
#include "include/private/SkTArray.h"
#include "include/private/SkTPin.h"
#include "include/private/SkTemplates.h"
#include "include/private/SkTo.h"
#include "modules/skshaper/include/SkShaper.h"
#include "modules/skshaper/include/SkShaper_factory.h"
#include "modules/skunicode/include/SkUnicode.h"
#include "src/core/SkFontPriv.h"
#include "src/core/SkUTF.h"

#include <algorithm>
#include <memory>
#include <numeric>
#include <optional>
#include <utility>

class SkPaint;

using namespace skia_private;

namespace skottie {
namespace {
static bool is_whitespace(char c) {
    // TODO: we've been getting away with this simple heuristic,
    // but ideally we should use SkUicode::isWhiteSpace().
    return c == ' ' || c == '\t' || c == '\r' || c == '\n';
}

// Helper for interfacing with SkShaper: buffers shaper-fed runs and performs
// per-line position adjustments (for external line breaking, horizontal alignment, etc).
class ResultBuilder final : public SkShaper::RunHandler {
public:
    ResultBuilder(const Shaper::TextDesc& desc, const SkRect& box, const sk_sp<SkFontMgr>& fontmgr,
                  const sk_sp<SkShapers::Factory>& shapingFactory)
            : fDesc(desc)
            , fBox(box)
            , fHAlignFactor(HAlignFactor(fDesc.fHAlign))
            , fFont(fDesc.fTypeface, fDesc.fTextSize)
            , fFontMgr(fontmgr)
            , fShapingFactory(shapingFactory) {
        // If the shaper callback returns null, fallback to the primitive shaper.
        SkASSERT(fShapingFactory);
        fShaper = fShapingFactory->makeShaper(fFontMgr);
        if (!fShaper) {
            fShaper = SkShapers::Primitive::PrimitiveText();
            fShapingFactory = SkShapers::Primitive::Factory();
        }
        fFont.setHinting(SkFontHinting::kNone);
        fFont.setSubpixel(true);
        fFont.setLinearMetrics(true);
        fFont.setBaselineSnap(false);
        fFont.setEdging(SkFont::Edging::kAntiAlias);
    }

    void beginLine() override {
        fLineGlyphs.reset(0);
        fLinePos.reset(0);
        fLineClusters.reset(0);
        fLineRuns.clear();
        fLineGlyphCount = 0;

        fCurrentPosition = fOffset;
        fPendingLineAdvance  = { 0, 0 };

        fLastLineDescent = 0;
    }

    void runInfo(const RunInfo& info) override {
        fPendingLineAdvance += info.fAdvance;

        SkFontMetrics metrics;
        info.fFont.getMetrics(&metrics);
        if (!fLineCount) {
            fFirstLineAscent = std::min(fFirstLineAscent, metrics.fAscent);
        }
        fLastLineDescent = std::max(fLastLineDescent, metrics.fDescent);
    }

    void commitRunInfo() override {}

    Buffer runBuffer(const RunInfo& info) override {
        // Skipping glyphless runs keeps every fLineRuns entry non-empty, which commitLine() and
        // the trailing tracking discount below rely on
        if (!info.glyphCount) {
            return {};
        }

        const auto run_start_index = fLineGlyphCount;
        fLineGlyphCount += info.glyphCount;

        fLineGlyphs.realloc(fLineGlyphCount);
        fLinePos.realloc(fLineGlyphCount);
        fLineClusters.realloc(fLineGlyphCount);
        fLineRuns.push_back({info.fFont, info.glyphCount});

        // Tracking is inter-glyph: the shaper appends it after every glyph, including the last
        // one on the line, but that trailing slack should not count toward the line width (else
        // it would e.g. push right-aligned text off the right edge).  runBuffer() is only called
        // for non-empty runs, so the line has at least one glyph -> discount one trailing unit.
        const auto line_advance = fPendingLineAdvance.x() - this->trackingAdvance();

        SkVector alignmentOffset { fHAlignFactor * (line_advance - fBox.width()), 0 };

        return {
            fLineGlyphs.get()   + run_start_index,
            fLinePos.get()      + run_start_index,
            nullptr,
            fLineClusters.get() + run_start_index,
            fCurrentPosition + alignmentOffset
        };
    }

    void commitRunBuffer(const RunInfo& info) override {
        fCurrentPosition += info.fAdvance;
    }

    void commitLine() override {
        fOffset.fY += fDesc.fLineHeight;

        // Observed AE handling of whitespace, for alignment purposes:
        //
        //   - leading whitespace contributes to alignment
        //   - trailing whitespace is ignored
        //   - auto line breaking retains all separating whitespace on the first line (no artificial
        //     leading WS is created).
        auto adjust_trailing_whitespace = [this]() {
            // For left-alignment, trailing WS doesn't make any difference.
            if (fLineRuns.empty() || fDesc.fHAlign == SkTextUtils::Align::kLeft_Align) {
                return;
            }

            // Technically, trailing whitespace could span multiple runs, but realistically,
            // SkShaper has no reason to split it.  Hence we're only checking the last run.
            size_t ws_count = 0;
            for (size_t i = 0; i < fLineRuns.back().fSize; ++i) {
                if (is_whitespace(fUTF8[fLineClusters[SkToInt(fLineGlyphCount - i - 1)]])) {
                    ++ws_count;
                } else {
                    break;
                }
            }

            // No trailing whitespace.
            if (!ws_count) {
                return;
            }

            // Compute the cumulative whitespace advance.  The shaper also appends tracking after
            // each of these glyphs, so include it to fully compensate for trailing whitespace.
            fAdvanceBuffer.resize(ws_count);
            fLineRuns.back().fFont.getWidths(
                     {fLineGlyphs.data() + fLineGlyphCount - ws_count, ws_count},
                     {fAdvanceBuffer.data(), ws_count});

            const auto ws_advance = std::accumulate(fAdvanceBuffer.begin(),
                                                    fAdvanceBuffer.end(),
                                                    0.0f)
                                  + ws_count*this->trackingAdvance();

            // Offset needed to compensate for whitespace.
            const auto offset = ws_advance*-fHAlignFactor;

            // Shift the whole line horizontally by the computed offset.
            std::transform(fLinePos.data(),
                           fLinePos.data() + fLineGlyphCount,
                           fLinePos.data(),
                           [&offset](SkPoint pos) { return SkPoint{pos.fX + offset, pos.fY}; });
        };

        adjust_trailing_whitespace();

        const auto commit_proc = (fDesc.fFlags & Shaper::Flags::kFragmentGlyphs)
            ? &ResultBuilder::commitFragementedRun
            : &ResultBuilder::commitConsolidatedRun;

        size_t run_offset = 0;
        for (const auto& rec : fLineRuns) {
            SkASSERT(run_offset < fLineGlyphCount);
            (this->*commit_proc)(rec,
                        fLineGlyphs.get()   + run_offset,
                        fLinePos.get()      + run_offset,
                        fLineClusters.get() + run_offset,
                        fLineCount);
            run_offset += rec.fSize;
        }

        fLineCount++;
    }

    Shaper::Result finalize(SkSize* shaped_size) {
        if (!(fDesc.fFlags & Shaper::Flags::kFragmentGlyphs)) {
            // All glyphs (if any) are pending in a single fragment.
            SkASSERT(fResult.fFragments.size() <= 1);
        }

        const auto ascent = this->ascent();

        // For visual VAlign modes, we use a hybrid extent box computed as the union of
        // actual visual bounds and the vertical typographical extent.
        //
        // This ensures that
        //
        //   a) text doesn't visually overflow the alignment boundaries
        //
        //   b) leading/trailing empty lines are still taken into account for alignment purposes

        auto extent_box = [&](bool include_typographical_extent) {
            auto box = fResult.computeVisualBounds();

            if (include_typographical_extent) {
                // Hybrid visual alignment mode, based on typographical extent.

                // By default, first line is vertically-aligned on a baseline of 0.
                // The typographical height considered for vertical alignment is the distance
                // between the first line top (ascent) to the last line bottom (descent).
                const auto typographical_top    = fBox.fTop + ascent,
                           typographical_bottom = fBox.fTop + fLastLineDescent +
                                          fDesc.fLineHeight*(fLineCount > 0 ? fLineCount - 1 : 0ul);

                box.fTop    = std::min(box.fTop,    typographical_top);
                box.fBottom = std::max(box.fBottom, typographical_bottom);
            }

            return box;
        };

        // Only compute the extent box when needed.
        std::optional<SkRect> ebox;

        // Vertical adjustments.
        float v_offset = -fDesc.fLineShift;

        switch (fDesc.fVAlign) {
        case Shaper::VAlign::kTop:
            v_offset -= ascent;
            break;
        case Shaper::VAlign::kTopBaseline:
            // Default behavior.
            break;
        case Shaper::VAlign::kHybridTop:
        case Shaper::VAlign::kVisualTop:
            ebox.emplace(extent_box(fDesc.fVAlign == Shaper::VAlign::kHybridTop));
            v_offset += fBox.fTop - ebox->fTop;
            break;
        case Shaper::VAlign::kHybridCenter:
        case Shaper::VAlign::kVisualCenter:
            ebox.emplace(extent_box(fDesc.fVAlign == Shaper::VAlign::kHybridCenter));
            v_offset += fBox.centerY() - ebox->centerY();
            break;
        case Shaper::VAlign::kHybridBottom:
        case Shaper::VAlign::kVisualBottom:
            ebox.emplace(extent_box(fDesc.fVAlign == Shaper::VAlign::kHybridBottom));
            v_offset += fBox.fBottom - ebox->fBottom;
            break;
        }

        if (shaped_size) {
            if (!ebox.has_value()) {
                ebox.emplace(extent_box(true));
            }
            *shaped_size = SkSize::Make(ebox->width(), ebox->height());
        }

        if (v_offset) {
            for (auto& fragment : fResult.fFragments) {
                fragment.fOrigin.fY += v_offset;
            }
        }

        return std::move(fResult);
    }

    void shapeLine(const char* start, const char* end, size_t utf8_offset) {
        if (!fShaper) {
            return;
        }

        SkASSERT(start <= end);
        if (start == end) {
            // SkShaper doesn't care for empty lines.
            this->beginLine();
            this->commitLine();

            // The calls above perform bookkeeping, but they do not add any fragments (since there
            // are no runs to commit).
            //
            // Certain Skottie features (line-based range selectors) do require accurate indexing
            // information even for empty lines though -- so we inject empty fragments solely for
            // line index tracking.
            //
            // Note: we don't add empty fragments in consolidated mode because 1) consolidated mode
            // assumes there is a single result fragment and 2) kFragmentGlyphs is always enabled
            // for cases where line index tracking is relevant.
            //
            // TODO(fmalita): investigate whether it makes sense to move this special case down
            // to commitFragmentedRun().
            if (fDesc.fFlags & Shaper::Flags::kFragmentGlyphs) {
                fResult.fFragments.push_back({
                    Shaper::ShapedGlyphs(),
                    {fBox.x(),fBox.y()},
                    0, 0,
                    fLineCount - 1,
                    false
                });
            }

            return;
        }

        // In default paragraph mode (VAlign::kTop), AE clips out lines when the baseline
        // goes below the box lower edge.
        if (fDesc.fVAlign == Shaper::VAlign::kTop) {
            // fOffset is relative to the first line baseline.
            const auto max_offset = fBox.height() + this->ascent(); // NB: ascent is negative
            if (fOffset.y() > max_offset) {
                return;
            }
        }

        const auto shape_width  = fDesc.fLinebreak == Shaper::LinebreakPolicy::kExplicit
                                    ? SK_ScalarMax
                                    : fBox.width();
        const auto shape_ltr    = fDesc.fDirection == Shaper::Direction::kLTR;
        const auto shape_track  = this->trackingEm();
        const size_t utf8_bytes = SkToSizeT(end - start);

        static constexpr uint8_t kBidiLevelLTR = 0,
                                 kBidiLevelRTL = 1;
        const auto lang_iter = fDesc.fLocale
                ? std::make_unique<SkShaper::TrivialLanguageRunIterator>(fDesc.fLocale, utf8_bytes)
                : SkShaper::MakeStdLanguageRunIterator(start, utf8_bytes);
#if defined(SKOTTIE_TRIVIAL_FONTRUN_ITER)
        // Chrome Linux/CrOS does not have a fallback-capable fontmgr, and crashes if fallback is
        // triggered.  Using a TrivialFontRunIterator avoids the issue (https://crbug.com/1520148).
        const auto font_iter = std::make_unique<SkShaper::TrivialFontRunIterator>(fFont,
                                                                                  utf8_bytes);
#else
        const auto font_iter = SkShaper::MakeFontMgrRunIterator(
                                    start, utf8_bytes, fFont,
                                    fFontMgr ? fFontMgr : SkFontMgr::RefEmpty(), // used as fallback
                                    fDesc.fFontFamily,
                                    fFont.getTypeface()->fontStyle(),
                                    lang_iter.get());
#endif

        std::unique_ptr<SkShaper::BiDiRunIterator> bidi_iter =
                fShapingFactory->makeBidiRunIterator(start, utf8_bytes,
                                                  shape_ltr ? kBidiLevelLTR : kBidiLevelRTL);
        if (!bidi_iter) {
            bidi_iter = std::make_unique<SkShaper::TrivialBiDiRunIterator>(
                    shape_ltr ? kBidiLevelLTR : kBidiLevelRTL, utf8_bytes);
        }

        constexpr SkFourByteTag unknownScript = SkSetFourByteTag('Z', 'z', 'z', 'z');
        std::unique_ptr<SkShaper::ScriptRunIterator> scpt_iter =
                fShapingFactory->makeScriptRunIterator(start, utf8_bytes, unknownScript);
        if (!scpt_iter) {
            scpt_iter = std::make_unique<SkShaper::TrivialScriptRunIterator>(unknownScript, utf8_bytes);
        }

        if (!font_iter || !bidi_iter || !scpt_iter || !lang_iter) {
            return;
        }

        fUTF8 = start;
        fUTF8Offset = utf8_offset;
        fShaper->shape({ start, utf8_bytes },
                       *font_iter,
                       *bidi_iter,
                       *scpt_iter,
                       *lang_iter,
                       {},
                       { .width = shape_width, .tracking = shape_track },
                       this);
        fUTF8 = nullptr;
    }

private:
    void commitFragementedRun(const skottie::Shaper::RunRec& run,
                              const SkGlyphID* glyphs,
                              const SkPoint* pos,
                              const uint32_t* clusters,
                              uint32_t line_index) {
        float ascent = 0;

        if (fDesc.fFlags & Shaper::Flags::kTrackFragmentAdvanceAscent) {
            SkFontMetrics metrics;
            run.fFont.getMetrics(&metrics);
            ascent = metrics.fAscent;

            // Note: we use per-glyph advances for anchoring, but it's unclear whether this
            // is exactly the same as AE.  E.g. are 'acute' glyphs anchored separately for fonts
            // in which they're distinct?
            fAdvanceBuffer.resize(run.fSize);
            run.fFont.getWidths({glyphs, run.fSize}, {fAdvanceBuffer.data(), run.fSize});
        }

        // In fragmented mode we immediately push the glyphs to fResult,
        // one fragment per glyph.  Glyph positioning is externalized
        // (positions returned in Fragment::fPos).
        for (size_t i = 0; i < run.fSize; ++i) {
            const auto advance = (fDesc.fFlags & Shaper::Flags::kTrackFragmentAdvanceAscent)
                    ? fAdvanceBuffer[SkToInt(i)]
                    : 0.0f;

            fResult.fFragments.push_back({
                {
                    { {run.fFont, 1} },
                    { glyphs[i] },
                    { {0,0} },
                    fDesc.fFlags & Shaper::kClusters
                        ? std::vector<size_t>{ fUTF8Offset + clusters[i] }
                        : std::vector<size_t>({}),
                },
                { fBox.x() + pos[i].fX, fBox.y() + pos[i].fY },
                advance, ascent,
                line_index, is_whitespace(fUTF8[clusters[i]])
            });

            // Note: we only check the first code point in the cluster for whitespace.
            // It's unclear whether thers's a saner approach.
            fResult.fMissingGlyphCount += (glyphs[i] == kMissingGlyphID);
        }
    }

    void commitConsolidatedRun(const skottie::Shaper::RunRec& run,
                               const SkGlyphID* glyphs,
                               const SkPoint* pos,
                               const uint32_t* clusters,
                               uint32_t) {
        // In consolidated mode we just accumulate glyphs to a single fragment in ResultBuilder.
        // Glyph positions are baked in the fragment runs (Fragment::fPos only reflects the
        // box origin).

        if (fResult.fFragments.empty()) {
            fResult.fFragments.push_back({{{}, {}, {}, {}}, {fBox.x(), fBox.y()}, 0, 0, 0, false});
        }

        auto& current_glyphs = fResult.fFragments.back().fGlyphs;
        current_glyphs.fRuns.push_back(run);
        current_glyphs.fGlyphIDs.insert(current_glyphs.fGlyphIDs.end(), glyphs, glyphs + run.fSize);
        current_glyphs.fGlyphPos.insert(current_glyphs.fGlyphPos.end(), pos   , pos    + run.fSize);

        for (size_t i = 0; i < run.fSize; ++i) {
            fResult.fMissingGlyphCount += (glyphs[i] == kMissingGlyphID);
        }

        if (fDesc.fFlags & Shaper::kClusters) {
            current_glyphs.fClusters.reserve(current_glyphs.fClusters.size() + run.fSize);
            for (size_t i = 0; i < run.fSize; ++i) {
                current_glyphs.fClusters.push_back(fUTF8Offset + clusters[i]);
            }
        }
    }

    static float HAlignFactor(SkTextUtils::Align align) {
        switch (align) {
        case SkTextUtils::kLeft_Align:   return  0.0f;
        case SkTextUtils::kCenter_Align: return -0.5f;
        case SkTextUtils::kRight_Align:  return -1.0f;
        }
        return 0.0f; // go home, msvc...
    }

    SkScalar ascent() const {
        // Use the explicit ascent, when specified.
        // Note: ascent values are negative (relative to the baseline).
        return fDesc.fAscent ? fDesc.fAscent : fFirstLineAscent;
    }

    // Tracking expressed as a fraction of the font size (the unit SkShaper expects).
    float trackingEm() const {
        static constexpr float kTrackingUnitsPerEm = 1000;
        return fDesc.fTextTracking / kTrackingUnitsPerEm;
    }

    // Tracking in absolute (text-space) units, applied by the shaper after each glyph.
    // Mirrors the backends' formula (trackingEm * size * scaleX) so the discount matches.
    SkScalar trackingAdvance() const {
        return this->trackingEm() * fFont.getSize() * fFont.getScaleX();
    }

    inline static constexpr SkGlyphID kMissingGlyphID = 0;

    const Shaper::TextDesc&   fDesc;
    const SkRect&             fBox;
    const float               fHAlignFactor;

    SkFont                          fFont;
    const sk_sp<SkFontMgr>          fFontMgr;
    std::unique_ptr<SkShaper>       fShaper;
    sk_sp<SkShapers::Factory>       fShapingFactory;

    AutoSTMalloc<64, SkGlyphID>          fLineGlyphs;
    AutoSTMalloc<64, SkPoint>            fLinePos;
    AutoSTMalloc<64, uint32_t>           fLineClusters;
    STArray<16, skottie::Shaper::RunRec> fLineRuns;
    size_t                                 fLineGlyphCount = 0;

    STArray<64, float, true> fAdvanceBuffer;

    SkPoint  fCurrentPosition{ 0, 0 };
    SkPoint  fOffset{ 0, 0 };
    SkVector fPendingLineAdvance{ 0, 0 };
    uint32_t fLineCount = 0;
    float    fFirstLineAscent = 0,
             fLastLineDescent = 0;

    const char* fUTF8       = nullptr; // only valid during shapeLine() calls
    size_t      fUTF8Offset = 0;       // current line offset within the original string

    Shaper::Result fResult;
};

Shaper::Result ShapeImpl(const SkString& txt, const Shaper::TextDesc& desc,
                         const SkRect& box, const sk_sp<SkFontMgr>& fontmgr,
                         const sk_sp<SkShapers::Factory>& shapingFactory,
                         SkSize* shaped_size) {
    const auto& is_line_break = [](SkUnichar uch) {
        // TODO: other explicit breaks?
        return uch == '\r';
    };

    const char* ptr        = txt.c_str();
    const char* line_start = ptr;
    const char* begin      = ptr;
    const char* end        = ptr + txt.size();

    ResultBuilder rbuilder(desc, box, fontmgr, shapingFactory);
    while (ptr < end) {
        if (is_line_break(SkUTF::NextUTF8(&ptr, end))) {
            rbuilder.shapeLine(line_start, ptr - 1, SkToSizeT(line_start - begin));
            line_start = ptr;
        }
    }
    rbuilder.shapeLine(line_start, ptr, SkToSizeT(line_start - begin));

    return rbuilder.finalize(shaped_size);
}

bool result_fits(const Shaper::Result& res, const SkSize& res_size,
                 const SkRect& box, const Shaper::TextDesc& desc) {
    // optional max line count constraint
    if (desc.fMaxLines) {
        const auto line_count = res.fFragments.empty()
                ? 0
                : res.fFragments.back().fLineIndex + 1;
        if (line_count > desc.fMaxLines) {
            return false;
        }
    }

    // geometric constraint
    return res_size.width() <= box.width() && res_size.height() <= box.height();
}

Shaper::Result ShapeToFit(const SkString& txt, const Shaper::TextDesc& orig_desc,
                          const SkRect& box, const sk_sp<SkFontMgr>& fontmgr,
                          const sk_sp<SkShapers::Factory>& shapingFactory) {
    Shaper::Result best_result;

    if (box.isEmpty() || orig_desc.fTextSize <= 0) {
        return best_result;
    }

    auto desc = orig_desc;

    const auto min_scale = std::max(desc.fMinTextSize / desc.fTextSize, 0.0f),
               max_scale = std::max(desc.fMaxTextSize / desc.fTextSize, min_scale);

    float in_scale = min_scale,                          // maximum scale that fits inside
         out_scale = max_scale,                          // minimum scale that doesn't fit
         try_scale = SkTPin(1.0f, min_scale, max_scale); // current probe

    // Perform a binary search for the best vertical fit (SkShaper already handles
    // horizontal fitting), starting with the specified text size.
    //
    // This hybrid loop handles both the binary search (when in/out extremes are known), and an
    // exponential search for the extremes.
    static constexpr size_t kMaxIter = 16;
    for (size_t i = 0; i < kMaxIter; ++i) {
        SkASSERT(try_scale >= in_scale && try_scale <= out_scale);
        desc.fTextSize   = try_scale * orig_desc.fTextSize;
        desc.fLineHeight = try_scale * orig_desc.fLineHeight;
        desc.fLineShift  = try_scale * orig_desc.fLineShift;
        desc.fAscent     = try_scale * orig_desc.fAscent;

        SkSize res_size = {0, 0};
        auto res = ShapeImpl(txt, desc, box, fontmgr, shapingFactory, &res_size);

        const auto prev_scale = try_scale;
        if (!result_fits(res, res_size, box, desc)) {
            out_scale = try_scale;
            try_scale = (in_scale == min_scale)
                    // initial in_scale not found yet - search exponentially
                    ? std::max(min_scale, try_scale * 0.5f)
                    // in_scale found - binary search
                    : (in_scale + out_scale) * 0.5f;
        } else {
            // It fits - so it's a candidate.
            best_result = std::move(res);
            best_result.fScale = try_scale;

            in_scale = try_scale;
            try_scale = (out_scale == max_scale)
                    // initial out_scale not found yet - search exponentially
                    ? std::min(max_scale, try_scale * 2)
                    // out_scale found - binary search
                    : (in_scale + out_scale) * 0.5f;
        }

        if (try_scale == prev_scale) {
            // no more progress
            break;
        }
    }

    return best_result;
}


// Applies capitalization rules.
class AdjustedText {
public:
    AdjustedText(const SkString& txt, const Shaper::TextDesc& desc, SkUnicode* unicode)
        : fText(txt) {
        switch (desc.fCapitalization) {
        case Shaper::Capitalization::kNone:
            break;
        case Shaper::Capitalization::kUpperCase:
            if (unicode) {
                fText = unicode->toUpper(fText);
            }
            break;
        }
    }

    operator const SkString&() const { return fText; }

private:
    SkString fText;
};

} // namespace

Shaper::Result Shaper::Shape(const SkString& text, const TextDesc& desc, const SkPoint& point,
                             const sk_sp<SkFontMgr>& fontmgr, const sk_sp<SkShapers::Factory>& shapingFactory) {
    const AdjustedText adjText(text, desc, shapingFactory->getUnicode());

    return (desc.fResize == ResizePolicy::kScaleToFit ||
            desc.fResize == ResizePolicy::kDownscaleToFit) // makes no sense in point mode
            ? Result()
            : ShapeImpl(adjText, desc, SkRect::MakeEmpty().makeOffset(point.x(), point.y()),
                        fontmgr, shapingFactory, nullptr);
}

Shaper::Result Shaper::Shape(const SkString& text, const TextDesc& desc, const SkRect& box,
                             const sk_sp<SkFontMgr>& fontmgr, const sk_sp<SkShapers::Factory>& shapingFactory) {
    const AdjustedText adjText(text, desc, shapingFactory->getUnicode());

    switch(desc.fResize) {
    case ResizePolicy::kNone:
        return ShapeImpl(adjText, desc, box, fontmgr, shapingFactory, nullptr);
    case ResizePolicy::kScaleToFit:
        return ShapeToFit(adjText, desc, box, fontmgr, shapingFactory);
    case ResizePolicy::kDownscaleToFit: {
        SkSize size;
        auto result = ShapeImpl(adjText, desc, box, fontmgr, shapingFactory, &size);

        return result_fits(result, size, box, desc)
                ? result
                : ShapeToFit(adjText, desc, box, fontmgr, shapingFactory);
    }
    }

    SkUNREACHABLE;
}

SkRect Shaper::ShapedGlyphs::computeBounds(BoundsType btype) const {
    auto bounds = SkRect::MakeEmpty();

    AutoSTArray<16, SkRect> glyphBounds;

    size_t offset = 0;
    for (const auto& run : fRuns) {
        SkRect font_bounds;
        if (btype == BoundsType::kConservative) {
            font_bounds = SkFontPriv::GetFontBounds(run.fFont);

            // Empty font bounds is likely a font bug -- fall back to tight bounds.
            if (font_bounds.isEmpty()) {
                btype = BoundsType::kTight;
            }
        }

        switch (btype) {
        case BoundsType::kConservative: {
            SkRect run_bounds = SkRect::BoundsOrEmpty({fGlyphPos.data() + offset, run.fSize});
            run_bounds.fLeft   += font_bounds.left();
            run_bounds.fTop    += font_bounds.top();
            run_bounds.fRight  += font_bounds.right();
            run_bounds.fBottom += font_bounds.bottom();

            bounds.join(run_bounds);
        } break;
        case BoundsType::kTight: {
            glyphBounds.reset(SkToInt(run.fSize));
            run.fFont.getBounds({fGlyphIDs.data() + offset, run.fSize}, glyphBounds, nullptr);

            for (size_t i = 0; i < run.fSize; ++i) {
                bounds.join(glyphBounds[SkToInt(i)].makeOffset(fGlyphPos[offset + i]));
            }
        } break;
        }

        offset += run.fSize;
    }

    return bounds;
}

void Shaper::ShapedGlyphs::draw(SkCanvas* canvas,
                                const SkPoint& origin,
                                const SkPaint& paint) const {
    size_t offset = 0;
    for (const auto& run : fRuns) {
        canvas->drawGlyphs({fGlyphIDs.data() + offset, run.fSize},
                           {fGlyphPos.data() + offset, run.fSize},
                           origin,
                           run.fFont,
                           paint);
        offset += run.fSize;
    }
}

SkRect Shaper::Result::computeVisualBounds() const {
    auto bounds = SkRect::MakeEmpty();

    for (const auto& frag: fFragments) {
        bounds.join(frag.fGlyphs.computeBounds(ShapedGlyphs::BoundsType::kTight)
                                .makeOffset(frag.fOrigin));
    }

    return bounds;
}

} // namespace skottie
