// Copyright 2019 Google LLC.
#include "include/core/SkCanvas.h"
#include "include/core/SkFontMetrics.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPath.h"
#include "include/core/SkPathBuilder.h"
#include "include/core/SkPictureRecorder.h"
#include "include/core/SkSpan.h"
#include "include/core/SkTypeface.h"
#include "include/private/base/SkTFitsIn.h"
#include "include/private/base/SkTo.h"
#include "modules/skparagraph/include/Metrics.h"
#include "modules/skparagraph/include/Paragraph.h"
#include "modules/skparagraph/include/ParagraphPainter.h"
#include "modules/skparagraph/include/ParagraphStyle.h"
#include "modules/skparagraph/include/TextStyle.h"
#include "modules/skparagraph/src/OneLineShaper.h"
#include "modules/skparagraph/src/ParagraphImpl.h"
#include "modules/skparagraph/src/ParagraphPainterImpl.h"
#include "modules/skparagraph/src/Run.h"
#include "modules/skparagraph/src/TextLine.h"
#include "modules/skparagraph/src/TextWrapper.h"
#include "modules/skunicode/include/SkUnicode.h"
#include "src/base/SkUTF.h"
#include "src/core/SkTextBlobPriv.h"

#include <algorithm>
#include <cfloat>
#include <cmath>
#include <utility>

using namespace skia_private;

namespace skia {
namespace textlayout {

namespace {

SkScalar littleRound(SkScalar a) {
    // This rounding is done to match Flutter tests. Must be removed..
    auto val = std::fabs(a);
    if (val < 10000) {
        return SkScalarRoundToScalar(a * 100.0)/100.0;
    } else if (val < 100000) {
        return SkScalarRoundToScalar(a * 10.0)/10.0;
    } else {
        return SkScalarFloorToScalar(a);
    }
}
}  // namespace

TextRange operator*(const TextRange& a, const TextRange& b) {
    if (a.start == b.start && a.end == b.end) return a;
    auto begin = std::max(a.start, b.start);
    auto end = std::min(a.end, b.end);
    return end > begin ? TextRange(begin, end) : EMPTY_TEXT;
}

Paragraph::Paragraph(ParagraphStyle style, sk_sp<FontCollection> fonts)
            : fFontCollection(std::move(fonts))
            , fParagraphStyle(std::move(style))
            , fAlphabeticBaseline(0)
            , fIdeographicBaseline(0)
            , fHeight(0)
            , fWidth(0)
            , fMaxIntrinsicWidth(0)
            , fMinIntrinsicWidth(0)
            , fLongestLine(0)
            , fExceededMaxLines(0)
{
    SkASSERT(fFontCollection);
}

ParagraphImpl::ParagraphImpl(const SkString& text,
                             ParagraphStyle style,
                             TArray<Block, true> blocks,
                             TArray<Placeholder, true> placeholders,
                             sk_sp<FontCollection> fonts,
                             sk_sp<SkUnicode> unicode)
        : Paragraph(std::move(style), std::move(fonts))
        , fTextStyles(std::move(blocks))
        , fPlaceholders(std::move(placeholders))
        , fText(text)
        , fState(kUnknown)
        , fUnresolvedGlyphs(0)
        , fPicture(nullptr)
        , fStrutMetrics(false)
        , fOldWidth(0)
        , fOldHeight(0)
        , fUnicode(std::move(unicode))
        , fHasLineBreaks(false)
        , fHasWhitespacesInside(false)
        , fTrailingSpaces(0)
{
    SkASSERT(fUnicode);
}

ParagraphImpl::ParagraphImpl(const std::u16string& utf16text,
                             ParagraphStyle style,
                             TArray<Block, true> blocks,
                             TArray<Placeholder, true> placeholders,
                             sk_sp<FontCollection> fonts,
                             sk_sp<SkUnicode> unicode)
        : ParagraphImpl(SkString(),
                        std::move(style),
                        std::move(blocks),
                        std::move(placeholders),
                        std::move(fonts),
                        std::move(unicode))
{
    SkASSERT(fUnicode);
    fText =  SkUnicode::convertUtf16ToUtf8(utf16text);
}

ParagraphImpl::~ParagraphImpl() = default;

int32_t ParagraphImpl::unresolvedGlyphs() {
    if (fState < kShaped) {
        return -1;
    }

    return fUnresolvedGlyphs;
}

std::unordered_set<SkUnichar> ParagraphImpl::unresolvedCodepoints() {
    return fUnresolvedCodepoints;
}

void ParagraphImpl::addUnresolvedCodepoints(TextRange textRange) {
    fUnicode->forEachCodepoint(
        &fText[textRange.start], textRange.width(),
        [&](SkUnichar unichar, int32_t start, int32_t end, int32_t count) {
            fUnresolvedCodepoints.emplace(unichar);
        }
    );
}

void ParagraphImpl::layout(SkScalar rawWidth) {
    // TODO: This rounding is done to match Flutter tests. Must be removed...
    auto floorWidth = rawWidth;
    if (getApplyRoundingHack()) {
        floorWidth = SkScalarFloorToScalar(floorWidth);
    }

    if ((!SkIsFinite(rawWidth) || fLongestLine <= floorWidth) &&
        fState >= kLineBroken &&
         fLines.size() == 1 && fLines.front().ellipsis() == nullptr) {
        // Most common case: one line of text (and one line is never justified, so no cluster shifts)
        // We cannot mark it as kLineBroken because the new width can be bigger than the old width
        fWidth = floorWidth;
        fState = kShaped;
    } else if (fState >= kLineBroken && fOldWidth != floorWidth) {
        // We can use the results from SkShaper but have to do EVERYTHING ELSE again
        fState = kShaped;
    } else {
        // Nothing changed case: we can reuse the data from the last layout
    }

    if (fState < kShaped) {
        // Check if we have the text in the cache and don't need to shape it again
        if (!fFontCollection->getParagraphCache()->findParagraph(this)) {
            if (fState < kIndexed) {
                // This only happens once at the first layout; the text is immutable
                // and there is no reason to repeat it
                if (this->computeCodeUnitProperties()) {
                    fState = kIndexed;
                }
            }
            this->fRuns.clear();
            this->fClusters.clear();
            this->fClustersIndexFromCodeUnit.clear();
            this->fClustersIndexFromCodeUnit.push_back_n(fText.size() + 1, EMPTY_INDEX);
            if (!this->shapeTextIntoEndlessLine()) {
                this->resetContext();
                // TODO: merge the two next calls - they always come together
                this->resolveStrut();
                this->computeEmptyMetrics();
                this->fLines.clear();

                // Set the important values that are not zero
                fWidth = floorWidth;
                fHeight = fEmptyMetrics.height();
                if (fParagraphStyle.getStrutStyle().getStrutEnabled() &&
                    fParagraphStyle.getStrutStyle().getForceStrutHeight()) {
                    fHeight = fStrutMetrics.height();
                }
                fAlphabeticBaseline = fEmptyMetrics.alphabeticBaseline();
                fIdeographicBaseline = fEmptyMetrics.ideographicBaseline();
                fLongestLine = FLT_MIN - FLT_MAX;  // That is what flutter has
                fMinIntrinsicWidth = 0;
                fMaxIntrinsicWidth = 0;
                this->fOldWidth = floorWidth;
                this->fOldHeight = this->fHeight;

                return;
            } else {
                // Add the paragraph to the cache
                fFontCollection->getParagraphCache()->updateParagraph(this);
            }
        }
        fState = kShaped;
    }

    if (fState == kShaped) {
        this->resetContext();
        this->resolveStrut();
        this->computeEmptyMetrics();
        this->fLines.clear();
        this->breakShapedTextIntoLines(floorWidth);
        fState = kLineBroken;
    }

    if (fState == kLineBroken) {
        // Build the picture lazily not until we actually have to paint (or never)
        this->resetShifts();
        this->formatLines(fWidth);
        fState = kFormatted;
    }

    this->fOldWidth = floorWidth;
    this->fOldHeight = this->fHeight;

    if (getApplyRoundingHack()) {
        // TODO: This rounding is done to match Flutter tests. Must be removed...
        fMinIntrinsicWidth = littleRound(fMinIntrinsicWidth);
        fMaxIntrinsicWidth = littleRound(fMaxIntrinsicWidth);
    }

    // TODO: This is strictly Flutter thing. Must be factored out into some flutter code
    if (fParagraphStyle.getMaxLines() == 1 ||
        (fParagraphStyle.unlimited_lines() && fParagraphStyle.ellipsized())) {
        fMinIntrinsicWidth = fMaxIntrinsicWidth;
    }

    // TODO: Since min and max are calculated differently it's possible to get a rounding error
    //  that would make min > max. Sort it out later, make it the same for now
    if (fMaxIntrinsicWidth < fMinIntrinsicWidth) {
        fMaxIntrinsicWidth = fMinIntrinsicWidth;
    }

    //SkDebugf("layout('%s', %f): %f %f\n", fText.c_str(), rawWidth, fMinIntrinsicWidth, fMaxIntrinsicWidth);
}

void ParagraphImpl::paint(SkCanvas* canvas, SkScalar x, SkScalar y) {
    CanvasParagraphPainter painter(canvas);
    paint(&painter, x, y);
}

void ParagraphImpl::paint(ParagraphPainter* painter, SkScalar x, SkScalar y) {
    for (auto& line : fLines) {
        line.paint(painter, x, y);
    }
}

void ParagraphImpl::resetContext() {
    fAlphabeticBaseline = 0;
    fHeight = 0;
    fWidth = 0;
    fIdeographicBaseline = 0;
    fMaxIntrinsicWidth = 0;
    fMinIntrinsicWidth = 0;
    fLongestLine = 0;
    fMaxWidthWithTrailingSpaces = 0;
    fExceededMaxLines = false;
}

// shapeTextIntoEndlessLine is the thing that calls this method
bool ParagraphImpl::computeCodeUnitProperties() {

    if (nullptr == fUnicode) {
        return false;
    }

    // Get bidi regions
    auto textDirection = fParagraphStyle.getTextDirection() == TextDirection::kLtr
                              ? SkUnicode::TextDirection::kLTR
                              : SkUnicode::TextDirection::kRTL;
    if (!fUnicode->getBidiRegions(fText.c_str(), fText.size(), textDirection, &fBidiRegions)) {
        return false;
    }

    // Collect all spaces and some extra information
    // (and also substitute \t with a space while we are at it)
    if (!fUnicode->computeCodeUnitFlags(&fText[0],
                                        fText.size(),
                                        this->paragraphStyle().getReplaceTabCharacters(),
                                        &fCodeUnitProperties)) {
        return false;
    }

    // Get some information about trailing spaces / hard line breaks
    fTrailingSpaces = fText.size();
    TextIndex firstWhitespace = EMPTY_INDEX;
    for (int i = 0; i < fCodeUnitProperties.size(); ++i) {
        auto flags = fCodeUnitProperties[i];
        if (SkUnicode::hasPartOfWhiteSpaceBreakFlag(flags)) {
            if (fTrailingSpaces  == fText.size()) {
                fTrailingSpaces = i;
            }
            if (firstWhitespace == EMPTY_INDEX) {
                firstWhitespace = i;
            }
        } else {
            fTrailingSpaces = fText.size();
        }
        if (SkUnicode::hasHardLineBreakFlag(flags)) {
            fHasLineBreaks = true;
        }
    }

    if (firstWhitespace < fTrailingSpaces) {
        fHasWhitespacesInside = true;
    }

    return true;
}

static bool is_ascii_7bit_space(int c) {
    SkASSERT(c >= 0 && c <= 127);

    // Extracted from https://en.wikipedia.org/wiki/Whitespace_character
    //
    enum WS {
        kHT    = 9,
        kLF    = 10,
        kVT    = 11,
        kFF    = 12,
        kCR    = 13,
        kSP    = 32,    // too big to use as shift
    };
#define M(shift)    (1 << (shift))
    constexpr uint32_t kSpaceMask = M(kHT) | M(kLF) | M(kVT) | M(kFF) | M(kCR);
    // we check for Space (32) explicitly, since it is too large to shift
    return (c == kSP) || (c <= 31 && (kSpaceMask & M(c)));
#undef M
}

Cluster::Cluster(ParagraphImpl* owner,
                 RunIndex runIndex,
                 size_t start,
                 size_t end,
                 SkSpan<const char> text,
                 SkScalar width,
                 SkScalar height)
        : fOwner(owner)
        , fRunIndex(runIndex)
        , fTextRange(text.begin() - fOwner->text().begin(), text.end() - fOwner->text().begin())
        , fGraphemeRange(EMPTY_RANGE)
        , fStart(start)
        , fEnd(end)
        , fWidth(width)
        , fHeight(height)
        , fHalfLetterSpacing(0.0)
        , fIsIdeographic(false) {
    size_t whiteSpacesBreakLen = 0;
    size_t intraWordBreakLen = 0;

    const char* ch = text.data();
    const char* chEnd = ch + text.size();
    if (chEnd - ch == 1 && *(const unsigned char*)ch <= 0x7F) {
        // I am not even sure it's worth it if we do not save a unicode call
        if (is_ascii_7bit_space(*ch)) {
            ++whiteSpacesBreakLen;
        }
    } else {
        for (auto i = fTextRange.start; i < fTextRange.end; ++i) {
            if (fOwner->codeUnitHasProperty(i, SkUnicode::CodeUnitFlags::kPartOfWhiteSpaceBreak)) {
                ++whiteSpacesBreakLen;
            }
            if (fOwner->codeUnitHasProperty(i, SkUnicode::CodeUnitFlags::kPartOfIntraWordBreak)) {
                ++intraWordBreakLen;
            }
            if (fOwner->codeUnitHasProperty(i, SkUnicode::CodeUnitFlags::kIdeographic)) {
                fIsIdeographic = true;
            }
        }
    }

    fIsWhiteSpaceBreak = whiteSpacesBreakLen == fTextRange.width();
    fIsIntraWordBreak = intraWordBreakLen == fTextRange.width();
    fIsHardBreak = fOwner->codeUnitHasProperty(fTextRange.end,
                                               SkUnicode::CodeUnitFlags::kHardLineBreakBefore);
}

SkScalar Run::calculateWidth(size_t start, size_t end, bool clip) const {
    SkASSERT(start <= end);
    // clip |= end == size();  // Clip at the end of the run?
    auto correction = 0.0f;
    if (end > start && !fJustificationShifts.empty()) {
        // This is not a typo: we are using Point as a pair of SkScalars
        correction = fJustificationShifts[end - 1].fX -
                     fJustificationShifts[start].fY;
    }
    return posX(end) - posX(start) + correction;
}

// In some cases we apply spacing to glyphs first and then build the cluster table, in some we do
// the opposite - just to optimize the most common case.
void ParagraphImpl::applySpacingAndBuildClusterTable() {

    // Check all text styles to see what we have to do (if anything)
    size_t letterSpacingStyles = 0;
    bool hasWordSpacing = false;
    for (auto& block : fTextStyles) {
        if (block.fRange.width() > 0) {
            if (!SkScalarNearlyZero(block.fStyle.getLetterSpacing())) {
                ++letterSpacingStyles;
            }
            if (!SkScalarNearlyZero(block.fStyle.getWordSpacing())) {
                hasWordSpacing = true;
            }
        }
    }

    if (letterSpacingStyles == 0 && !hasWordSpacing) {
        // We don't have to do anything about spacing (most common case)
        this->buildClusterTable();
        return;
    }

    if (letterSpacingStyles == 1 && !hasWordSpacing && fTextStyles.size() == 1 &&
        fTextStyles[0].fRange.width() == fText.size() && fRuns.size() == 1) {
        // We have to letter space the entire paragraph (second most common case)
        auto& run = fRuns[0];
        auto& style = fTextStyles[0].fStyle;
        run.addLetterSpacesEvenly(style.getLetterSpacing());

        this->buildClusterTable();

        // This is something Flutter requires
        for (auto& cluster : fClusters) {
            cluster.setHalfLetterSpacing(style.getLetterSpacing() / 2);
        }

        return;
    }

    // The complex case: many text styles with spacing (possibly not adjusted to glyphs)
    this->buildClusterTable();

    // Walk through all the clusters in the direction of shaped text
    // (we have to walk through the styles in the same order, too)
    // Not breaking the iteration on every run!
    SkScalar shift = 0;
    bool soFarWhitespacesOnly = true;
    bool wordSpacingPending = false;
    Cluster* lastSpaceCluster = nullptr;
    for (auto& run : fRuns) {

        // Skip placeholder runs
        if (run.isPlaceholder()) {
            continue;
        }

        run.iterateThroughClusters([this, &run, &shift, &soFarWhitespacesOnly, &wordSpacingPending, &lastSpaceCluster](Cluster* cluster) {
            // Shift the cluster (shift collected from the previous clusters)
            run.shift(cluster, shift);

            // Synchronize styles (one cluster can be covered by few styles)
            Block* currentStyle = fTextStyles.begin();
            while (!cluster->startsIn(currentStyle->fRange)) {
                currentStyle++;
                SkASSERT(currentStyle != fTextStyles.end());
            }

            SkASSERT(!currentStyle->fStyle.isPlaceholder());

            // Process word spacing
            if (currentStyle->fStyle.getWordSpacing() != 0) {
                if (cluster->isWhitespaceBreak() && cluster->isSoftBreak()) {
                    if (!soFarWhitespacesOnly) {
                        lastSpaceCluster = cluster;
                        wordSpacingPending = true;
                    }
                } else if (wordSpacingPending) {
                    SkScalar spacing = currentStyle->fStyle.getWordSpacing();
                    if (cluster->fRunIndex != lastSpaceCluster->fRunIndex) {
                        // If the last space cluster belongs to the previous run
                        // we have to extend that cluster and that run
                        lastSpaceCluster->run().addSpacesAtTheEnd(spacing, lastSpaceCluster);
                        lastSpaceCluster->run().extend(lastSpaceCluster, spacing);
                    } else {
                        run.addSpacesAtTheEnd(spacing, lastSpaceCluster);
                    }

                    run.shift(cluster, spacing);
                    shift += spacing;
                    wordSpacingPending = false;
                }
            }
            // Process letter spacing (it will be cancelled out for Script languages
            if ((currentStyle->fStyle.getLetterSpacing() != 0)) {
                shift +=
                        run.addLetterSpacesEvenly(currentStyle->fStyle.getLetterSpacing(), cluster);
            }

            if (soFarWhitespacesOnly && !cluster->isWhitespaceBreak()) {
                soFarWhitespacesOnly = false;
            }
        });
    }
}

// Clusters in the order of the input text
void ParagraphImpl::buildClusterTable() {
    // It's possible that one grapheme includes few runs; we cannot handle it
    // so we break graphemes by the runs instead
    // It's not the ideal solution and has to be revisited later
    int cluster_count = 1;
    for (auto& run : fRuns) {
        cluster_count += run.isPlaceholder() ? 1 : run.size();
        fCodeUnitProperties[run.fTextRange.start] |= SkUnicode::CodeUnitFlags::kGraphemeStart;
        fCodeUnitProperties[run.fTextRange.start] |= SkUnicode::CodeUnitFlags::kGlyphClusterStart;
    }
    if (!fRuns.empty()) {
        fCodeUnitProperties[fRuns.back().textRange().end] |= SkUnicode::CodeUnitFlags::kGraphemeStart;
        fCodeUnitProperties[fRuns.back().textRange().end] |= SkUnicode::CodeUnitFlags::kGlyphClusterStart;
    }
    fClusters.reserve_exact(fClusters.size() + cluster_count);

    // Walk through all the run in the direction of input text
    for (auto& run : fRuns) {
        auto runIndex = run.index();
        auto runStart = fClusters.size();
        if (run.isPlaceholder()) {
            // Add info to cluster indexes table (text -> cluster)
            for (auto i = run.textRange().start; i < run.textRange().end; ++i) {
              fClustersIndexFromCodeUnit[i] = fClusters.size();
            }
            // There are no glyphs but we want to have one cluster
            fClusters.emplace_back(this, runIndex, 0ul, 1ul, this->text(run.textRange()), run.advance().fX, run.advance().fY);
            fCodeUnitProperties[run.textRange().start] |= SkUnicode::CodeUnitFlags::kSoftLineBreakBefore;
            fCodeUnitProperties[run.textRange().end] |= SkUnicode::CodeUnitFlags::kSoftLineBreakBefore;
        } else {
            // Walk through the glyph in the direction of input text
            run.iterateThroughClustersInTextOrder([runIndex, this](size_t glyphStart,
                                                                   size_t glyphEnd,
                                                                   size_t charStart,
                                                                   size_t charEnd,
                                                                   SkScalar width,
                                                                   SkScalar height) {
                SkASSERT(charEnd >= charStart);
                // Add info to cluster indexes table (text -> cluster)
                for (auto i = charStart; i < charEnd; ++i) {
                  fClustersIndexFromCodeUnit[i] = fClusters.size();
                }
                SkSpan<const char> text(fText.c_str() + charStart, charEnd - charStart);
                fClusters.emplace_back(this, runIndex, glyphStart, glyphEnd, text, width, height);
                fCodeUnitProperties[charStart] |= SkUnicode::CodeUnitFlags::kGlyphClusterStart;
            });
        }
        fCodeUnitProperties[run.textRange().start] |= SkUnicode::CodeUnitFlags::kGlyphClusterStart;

        run.setClusterRange(runStart, fClusters.size());
        fMaxIntrinsicWidth += run.advance().fX;
    }
    fClustersIndexFromCodeUnit[fText.size()] = fClusters.size();
    fClusters.emplace_back(this, EMPTY_RUN, 0, 0, this->text({fText.size(), fText.size()}), 0, 0);
}

bool ParagraphImpl::shapeTextIntoEndlessLine() {

    if (fText.size() == 0) {
        return false;
    }

    fUnresolvedCodepoints.clear();
    fFontSwitches.clear();

    OneLineShaper oneLineShaper(this);
    auto result = oneLineShaper.shape();
    fUnresolvedGlyphs = oneLineShaper.unresolvedGlyphs();

    this->applySpacingAndBuildClusterTable();

    return result;
}

void ParagraphImpl::breakShapedTextIntoLines(SkScalar maxWidth) {

    if (!fHasLineBreaks &&
        !fHasWhitespacesInside &&
        fPlaceholders.size() == 1 &&
        fRuns.size() == 1 && fRuns[0].fAdvance.fX <= maxWidth) {
        // This is a short version of a line breaking when we know that:
        // 1. We have only one line of text
        // 2. It's shaped into a single run
        // 3. There are no placeholders
        // 4. There are no linebreaks (which will format text into multiple lines)
        // 5. There are no whitespaces so the minIntrinsicWidth=maxIntrinsicWidth
        // (To think about that, the last condition is not quite right;
        // we should calculate minIntrinsicWidth by soft line breaks.
        // However, it's how it's done in Flutter now)
        auto& run = this->fRuns[0];
        auto advance = run.advance();
        auto textRange = TextRange(0, this->text().size());
        auto textExcludingSpaces = TextRange(0, fTrailingSpaces);
        InternalLineMetrics metrics(this->strutForceHeight());
        metrics.add(&run);
        auto disableFirstAscent = this->paragraphStyle().getTextHeightBehavior() &
                                  TextHeightBehavior::kDisableFirstAscent;
        auto disableLastDescent = this->paragraphStyle().getTextHeightBehavior() &
                                  TextHeightBehavior::kDisableLastDescent;
        if (disableFirstAscent) {
            metrics.fAscent = metrics.fRawAscent;
        }
        if (disableLastDescent) {
            metrics.fDescent = metrics.fRawDescent;
        }
        if (this->strutEnabled()) {
            this->strutMetrics().updateLineMetrics(metrics);
        }
        ClusterIndex trailingSpaces = fClusters.size();
        do {
            --trailingSpaces;
            auto& cluster = fClusters[trailingSpaces];
            if (!cluster.isWhitespaceBreak()) {
                ++trailingSpaces;
                break;
            }
            advance.fX -= cluster.width();
        } while (trailingSpaces != 0);

        advance.fY = metrics.height();
        auto clusterRange = ClusterRange(0, trailingSpaces);
        auto clusterRangeWithGhosts = ClusterRange(0, this->clusters().size() - 1);
        this->addLine(SkPoint::Make(0, 0), advance,
                      textExcludingSpaces, textRange, textRange,
                      clusterRange, clusterRangeWithGhosts, run.advance().x(),
                      metrics);

        fLongestLine = nearlyZero(advance.fX) ? run.advance().fX : advance.fX;
        fHeight = advance.fY;
        fWidth = maxWidth;
        fMaxIntrinsicWidth = run.advance().fX;
        fMinIntrinsicWidth = advance.fX;
        fAlphabeticBaseline = fLines.empty() ? fEmptyMetrics.alphabeticBaseline() : fLines.front().alphabeticBaseline();
        fIdeographicBaseline = fLines.empty() ? fEmptyMetrics.ideographicBaseline() : fLines.front().ideographicBaseline();
        fExceededMaxLines = false;
        return;
    }

    TextWrapper textWrapper;
    textWrapper.breakTextIntoLines(
            this,
            maxWidth,
            [&](TextRange textExcludingSpaces,
                TextRange text,
                TextRange textWithNewlines,
                ClusterRange clusters,
                ClusterRange clustersWithGhosts,
                SkScalar widthWithSpaces,
                size_t startPos,
                size_t endPos,
                SkVector offset,
                SkVector advance,
                InternalLineMetrics metrics,
                bool addEllipsis) {
                // TODO: Take in account clipped edges
                auto& line = this->addLine(offset, advance, textExcludingSpaces, text, textWithNewlines, clusters, clustersWithGhosts, widthWithSpaces, metrics);
                if (addEllipsis) {
                    line.createEllipsis(maxWidth, this->getEllipsis(), true);
                }
                fLongestLine = std::max(fLongestLine, nearlyZero(line.width()) ? widthWithSpaces : line.width());
            });

    fHeight = textWrapper.height();
    fWidth = maxWidth;
    fMaxIntrinsicWidth = textWrapper.maxIntrinsicWidth();
    fMinIntrinsicWidth = textWrapper.minIntrinsicWidth();
    fAlphabeticBaseline = fLines.empty() ? fEmptyMetrics.alphabeticBaseline() : fLines.front().alphabeticBaseline();
    fIdeographicBaseline = fLines.empty() ? fEmptyMetrics.ideographicBaseline() : fLines.front().ideographicBaseline();
    fExceededMaxLines = textWrapper.exceededMaxLines();
}

void ParagraphImpl::formatLines(SkScalar maxWidth) {
    auto effectiveAlign = fParagraphStyle.effective_align();
    const bool isLeftAligned = effectiveAlign == TextAlign::kLeft
        || (effectiveAlign == TextAlign::kJustify && fParagraphStyle.getTextDirection() == TextDirection::kLtr);

    if (!SkIsFinite(maxWidth) && !isLeftAligned) {
        // Special case: clean all text in case of maxWidth == INF & align != left
        // We had to go through shaping though because we need all the measurement numbers
        fLines.clear();
        return;
    }

    for (auto& line : fLines) {
        line.format(effectiveAlign, maxWidth);
    }
}

void ParagraphImpl::resolveStrut() {
    auto strutStyle = this->paragraphStyle().getStrutStyle();
    if (!strutStyle.getStrutEnabled() || strutStyle.getFontSize() < 0) {
        return;
    }

    std::vector<sk_sp<SkTypeface>> typefaces = fFontCollection->findTypefaces(strutStyle.getFontFamilies(), strutStyle.getFontStyle(), std::nullopt);
    if (typefaces.empty()) {
        SkDEBUGF("Could not resolve strut font\n");
        return;
    }

    SkFont font(typefaces.front(), strutStyle.getFontSize());
    SkFontMetrics metrics;
    font.getMetrics(&metrics);
    const SkScalar strutLeading = strutStyle.getLeading() < 0 ? 0 : strutStyle.getLeading() * strutStyle.getFontSize();

    if (strutStyle.getHeightOverride()) {
        SkScalar strutAscent = 0.0f;
        SkScalar strutDescent = 0.0f;
        // The half leading flag doesn't take effect unless there's height override.
        if (strutStyle.getHalfLeading()) {
            const auto occupiedHeight = metrics.fDescent - metrics.fAscent;
            auto flexibleHeight = strutStyle.getHeight() * strutStyle.getFontSize() - occupiedHeight;
            // Distribute the flexible height evenly over and under.
            flexibleHeight /= 2;
            strutAscent = metrics.fAscent - flexibleHeight;
            strutDescent = metrics.fDescent + flexibleHeight;
        } else {
            const SkScalar strutMetricsHeight = metrics.fDescent - metrics.fAscent + metrics.fLeading;
            const auto strutHeightMultiplier = strutMetricsHeight == 0
              ? strutStyle.getHeight()
              : strutStyle.getHeight() * strutStyle.getFontSize() / strutMetricsHeight;
            strutAscent = metrics.fAscent * strutHeightMultiplier;
            strutDescent = metrics.fDescent * strutHeightMultiplier;
        }
        fStrutMetrics = InternalLineMetrics(
            strutAscent,
            strutDescent,
            strutLeading,
            metrics.fAscent, metrics.fDescent, metrics.fLeading);
    } else {
        fStrutMetrics = InternalLineMetrics(
                metrics.fAscent,
                metrics.fDescent,
                strutLeading);
    }
    fStrutMetrics.setForceStrut(this->paragraphStyle().getStrutStyle().getForceStrutHeight());
}

BlockRange ParagraphImpl::findAllBlocks(TextRange textRange) {
    BlockIndex begin = EMPTY_BLOCK;
    BlockIndex end = EMPTY_BLOCK;
    for (int index = 0; index < fTextStyles.size(); ++index) {
        auto& block = fTextStyles[index];
        if (block.fRange.end <= textRange.start) {
            continue;
        }
        if (block.fRange.start >= textRange.end) {
            break;
        }
        if (begin == EMPTY_BLOCK) {
            begin = index;
        }
        end = index;
    }

    if (begin == EMPTY_INDEX || end == EMPTY_INDEX) {
        // It's possible if some text is not covered with any text style
        // Not in Flutter but in direct use of SkParagraph
        return EMPTY_RANGE;
    }

    return { begin, end + 1 };
}

TextLine& ParagraphImpl::addLine(SkVector offset,
                                 SkVector advance,
                                 TextRange textExcludingSpaces,
                                 TextRange text,
                                 TextRange textIncludingNewLines,
                                 ClusterRange clusters,
                                 ClusterRange clustersWithGhosts,
                                 SkScalar widthWithSpaces,
                                 InternalLineMetrics sizes) {
    // Define a list of styles that covers the line
    auto blocks = findAllBlocks(textExcludingSpaces);
    return fLines.emplace_back(this, offset, advance, blocks,
                               textExcludingSpaces, text, textIncludingNewLines,
                               clusters, clustersWithGhosts, widthWithSpaces, sizes);
}

// Returns a vector of bounding boxes that enclose all text between
// start and end glyph indexes, including start and excluding end
std::vector<TextBox> ParagraphImpl::getRectsForRange(unsigned start,
                                                     unsigned end,
                                                     RectHeightStyle rectHeightStyle,
                                                     RectWidthStyle rectWidthStyle) {
    std::vector<TextBox> results;
    if (fText.isEmpty()) {
        if (start == 0 && end > 0) {
            // On account of implied "\n" that is always at the end of the text
            //SkDebugf("getRectsForRange(%d, %d): %f\n", start, end, fHeight);
            results.emplace_back(SkRect::MakeXYWH(0, 0, 0, fHeight), fParagraphStyle.getTextDirection());
        }
        return results;
    }

    this->ensureUTF16Mapping();

    if (start >= end || start > SkToSizeT(fUTF8IndexForUTF16Index.size()) || end == 0) {
        return results;
    }

    // Adjust the text to grapheme edges
    // Apparently, text editor CAN move inside graphemes but CANNOT select a part of it.
    // I don't know why - the solution I have here returns an empty box for every query that
    // does not contain an end of a grapheme.
    // Once a cursor is inside a complex grapheme I can press backspace and cause trouble.
    // To avoid any problems, I will not allow any selection of a part of a grapheme.
    // One flutter test fails because of it but the editing experience is correct
    // (although you have to press the cursor many times before it moves to the next grapheme).
    TextRange text(fText.size(), fText.size());
    // TODO: This is probably a temp change that makes SkParagraph work as TxtLib
    //  (so we can compare the results). We now include in the selection box only the graphemes
    //  that belongs to the given [start:end) range entirely (not the ones that intersect with it)
    if (start < SkToSizeT(fUTF8IndexForUTF16Index.size())) {
        auto utf8 = fUTF8IndexForUTF16Index[start];
        // If start points to a trailing surrogate, skip it
        if (start > 0 && fUTF8IndexForUTF16Index[start - 1] == utf8) {
            utf8 = fUTF8IndexForUTF16Index[start + 1];
        }
        text.start = this->findNextGraphemeBoundary(utf8);
    }
    if (end < SkToSizeT(fUTF8IndexForUTF16Index.size())) {
        auto utf8 = this->findPreviousGraphemeBoundary(fUTF8IndexForUTF16Index[end]);
        text.end = utf8;
    }
    //SkDebugf("getRectsForRange(%d,%d) -> (%d:%d)\n", start, end, text.start, text.end);
    for (auto& line : fLines) {
        auto lineText = line.textWithNewlines();
        auto intersect = lineText * text;
        if (intersect.empty() && lineText.start != text.start) {
            continue;
        }

        line.getRectsForRange(intersect, rectHeightStyle, rectWidthStyle, results);
    }
/*
    SkDebugf("getRectsForRange(%d, %d)\n", start, end);
    for (auto& r : results) {
        r.rect.fLeft = littleRound(r.rect.fLeft);
        r.rect.fRight = littleRound(r.rect.fRight);
        r.rect.fTop = littleRound(r.rect.fTop);
        r.rect.fBottom = littleRound(r.rect.fBottom);
        SkDebugf("[%f:%f * %f:%f]\n", r.rect.fLeft, r.rect.fRight, r.rect.fTop, r.rect.fBottom);
    }
*/
    return results;
}

std::vector<TextBox> ParagraphImpl::getRectsForPlaceholders() {
  std::vector<TextBox> boxes;
  if (fText.isEmpty()) {
       return boxes;
  }
  if (fPlaceholders.size() == 1) {
       // We always have one fake placeholder
       return boxes;
  }
  for (auto& line : fLines) {
      line.getRectsForPlaceholders(boxes);
  }
  /*
  SkDebugf("getRectsForPlaceholders('%s'): %d\n", fText.c_str(), boxes.size());
  for (auto& r : boxes) {
      r.rect.fLeft = littleRound(r.rect.fLeft);
      r.rect.fRight = littleRound(r.rect.fRight);
      r.rect.fTop = littleRound(r.rect.fTop);
      r.rect.fBottom = littleRound(r.rect.fBottom);
      SkDebugf("[%f:%f * %f:%f] %s\n", r.rect.fLeft, r.rect.fRight, r.rect.fTop, r.rect.fBottom,
               (r.direction == TextDirection::kLtr ? "left" : "right"));
  }
  */
  return boxes;
}

// TODO: Optimize (save cluster <-> codepoint connection)
PositionWithAffinity ParagraphImpl::getGlyphPositionAtCoordinate(SkScalar dx, SkScalar dy) {

    if (fText.isEmpty()) {
        return {0, Affinity::kDownstream};
    }

    this->ensureUTF16Mapping();

    for (auto& line : fLines) {
        // Let's figure out if we can stop looking
        auto offsetY = line.offset().fY;
        if (dy >= offsetY + line.height() && &line != &fLines.back()) {
            // This line is not good enough
            continue;
        }

        // This is so far the the line vertically closest to our coordinates
        // (or the first one, or the only one - all the same)

        auto result = line.getGlyphPositionAtCoordinate(dx);
        //SkDebugf("getGlyphPositionAtCoordinate(%f, %f): %d %s\n", dx, dy, result.position,
        //   result.affinity == Affinity::kUpstream ? "up" : "down");
        return result;
    }

    return {0, Affinity::kDownstream};
}

// Finds the first and last glyphs that define a word containing
// the glyph at index offset.
// By "glyph" they mean a character index - indicated by Minikin's code
SkRange<size_t> ParagraphImpl::getWordBoundary(unsigned offset) {

    if (fWords.empty()) {
        if (!fUnicode->getWords(fText.c_str(), fText.size(), nullptr, &fWords)) {
            return {0, 0 };
        }
    }

    int32_t start = 0;
    int32_t end = 0;
    for (size_t i = 0; i < fWords.size(); ++i) {
        auto word = fWords[i];
        if (word <= offset) {
            start = word;
            end = word;
        } else if (word > offset) {
            end = word;
            break;
        }
    }

    //SkDebugf("getWordBoundary(%d): %d - %d\n", offset, start, end);
    return { SkToU32(start), SkToU32(end) };
}

void ParagraphImpl::getLineMetrics(std::vector<LineMetrics>& metrics) {
    metrics.clear();
    for (auto& line : fLines) {
        metrics.emplace_back(line.getMetrics());
    }
}

SkSpan<const char> ParagraphImpl::text(TextRange textRange) {
    SkASSERT(textRange.start <= fText.size() && textRange.end <= fText.size());
    auto start = fText.c_str() + textRange.start;
    return SkSpan<const char>(start, textRange.width());
}

SkSpan<Cluster> ParagraphImpl::clusters(ClusterRange clusterRange) {
    SkASSERT(clusterRange.start < SkToSizeT(fClusters.size()) &&
             clusterRange.end <= SkToSizeT(fClusters.size()));
    return SkSpan<Cluster>(&fClusters[clusterRange.start], clusterRange.width());
}

Cluster& ParagraphImpl::cluster(ClusterIndex clusterIndex) {
    SkASSERT(clusterIndex < SkToSizeT(fClusters.size()));
    return fClusters[clusterIndex];
}

Run& ParagraphImpl::runByCluster(ClusterIndex clusterIndex) {
    auto start = cluster(clusterIndex);
    return this->run(start.fRunIndex);
}

SkSpan<Block> ParagraphImpl::blocks(BlockRange blockRange) {
    SkASSERT(blockRange.start < SkToSizeT(fTextStyles.size()) &&
             blockRange.end <= SkToSizeT(fTextStyles.size()));
    return SkSpan<Block>(&fTextStyles[blockRange.start], blockRange.width());
}

Block& ParagraphImpl::block(BlockIndex blockIndex) {
    SkASSERT(blockIndex < SkToSizeT(fTextStyles.size()));
    return fTextStyles[blockIndex];
}

void ParagraphImpl::setState(InternalState state) {
    if (fState <= state) {
        fState = state;
        return;
    }

    fState = state;
    switch (fState) {
        case kUnknown:
            SkASSERT(false);
            /*
            // The text is immutable and so are all the text indexing properties
            // taken from SkUnicode
            fCodeUnitProperties.reset();
            fWords.clear();
            fBidiRegions.clear();
            fUTF8IndexForUTF16Index.reset();
            fUTF16IndexForUTF8Index.reset();
            */
            [[fallthrough]];

        case kIndexed:
            fRuns.clear();
            fClusters.clear();
            [[fallthrough]];

        case kShaped:
            fLines.clear();
            [[fallthrough]];

        case kLineBroken:
            fPicture = nullptr;
            [[fallthrough]];

        default:
            break;
    }
}

void ParagraphImpl::computeEmptyMetrics() {

    // The empty metrics is used to define the height of the empty lines
    // Unfortunately, Flutter has 2 different cases for that:
    // 1. An empty line inside the text
    // 2. An empty paragraph
    // In the first case SkParagraph takes the metrics from the default paragraph style
    // In the second case it should take it from the current text style
    bool emptyParagraph = fRuns.empty();
    TextStyle textStyle = paragraphStyle().getTextStyle();
    if (emptyParagraph && !fTextStyles.empty()) {
        textStyle = fTextStyles.back().fStyle;
    }

    auto typefaces = fontCollection()->findTypefaces(
      textStyle.getFontFamilies(), textStyle.getFontStyle(), textStyle.getFontArguments());
    auto typeface = typefaces.empty() ? nullptr : typefaces.front();

    SkFont font(typeface, textStyle.getFontSize());
    fEmptyMetrics = InternalLineMetrics(font, paragraphStyle().getStrutStyle().getForceStrutHeight());

    if (!paragraphStyle().getStrutStyle().getForceStrutHeight() &&
        textStyle.getHeightOverride()) {
        const auto intrinsicHeight = fEmptyMetrics.height();
        const auto strutHeight = textStyle.getHeight() * textStyle.getFontSize();
        if (paragraphStyle().getStrutStyle().getHalfLeading()) {
            fEmptyMetrics.update(
                fEmptyMetrics.ascent(),
                fEmptyMetrics.descent(),
                fEmptyMetrics.leading() + strutHeight - intrinsicHeight);
        } else {
            const auto multiplier = strutHeight / intrinsicHeight;
            fEmptyMetrics.update(
                fEmptyMetrics.ascent() * multiplier,
                fEmptyMetrics.descent() * multiplier,
                fEmptyMetrics.leading() * multiplier);
        }
    }

    if (emptyParagraph) {
        // For an empty text we apply both TextHeightBehaviour flags
        // In case of non-empty paragraph TextHeightBehaviour flags will be applied at the appropriate place
        // We have to do it here because we skip wrapping for an empty text
        auto disableFirstAscent = (paragraphStyle().getTextHeightBehavior() & TextHeightBehavior::kDisableFirstAscent) == TextHeightBehavior::kDisableFirstAscent;
        auto disableLastDescent = (paragraphStyle().getTextHeightBehavior() & TextHeightBehavior::kDisableLastDescent) == TextHeightBehavior::kDisableLastDescent;
        fEmptyMetrics.update(
            disableFirstAscent ? fEmptyMetrics.rawAscent() : fEmptyMetrics.ascent(),
            disableLastDescent ? fEmptyMetrics.rawDescent() : fEmptyMetrics.descent(),
            fEmptyMetrics.leading());
    }

    if (fParagraphStyle.getStrutStyle().getStrutEnabled()) {
        fStrutMetrics.updateLineMetrics(fEmptyMetrics);
    }
}

SkString ParagraphImpl::getEllipsis() const {

    auto ellipsis8 = fParagraphStyle.getEllipsis();
    auto ellipsis16 = fParagraphStyle.getEllipsisUtf16();
    if (!ellipsis8.isEmpty()) {
        return ellipsis8;
    } else {
        return SkUnicode::convertUtf16ToUtf8(fParagraphStyle.getEllipsisUtf16());
    }
}

void ParagraphImpl::updateFontSize(size_t from, size_t to, SkScalar fontSize) {

  SkASSERT(from == 0 && to == fText.size());
  auto defaultStyle = fParagraphStyle.getTextStyle();
  defaultStyle.setFontSize(fontSize);
  fParagraphStyle.setTextStyle(defaultStyle);

  for (auto& textStyle : fTextStyles) {
    textStyle.fStyle.setFontSize(fontSize);
  }

  fState = std::min(fState, kIndexed);
  fOldWidth = 0;
  fOldHeight = 0;
}

void ParagraphImpl::updateTextAlign(TextAlign textAlign) {
    fParagraphStyle.setTextAlign(textAlign);

    if (fState >= kLineBroken) {
        fState = kLineBroken;
    }
}

void ParagraphImpl::updateForegroundPaint(size_t from, size_t to, SkPaint paint) {
    SkASSERT(from == 0 && to == fText.size());
    auto defaultStyle = fParagraphStyle.getTextStyle();
    defaultStyle.setForegroundColor(paint);
    fParagraphStyle.setTextStyle(defaultStyle);

    for (auto& textStyle : fTextStyles) {
        textStyle.fStyle.setForegroundColor(paint);
    }
}

void ParagraphImpl::updateBackgroundPaint(size_t from, size_t to, SkPaint paint) {
    SkASSERT(from == 0 && to == fText.size());
    auto defaultStyle = fParagraphStyle.getTextStyle();
    defaultStyle.setBackgroundColor(paint);
    fParagraphStyle.setTextStyle(defaultStyle);

    for (auto& textStyle : fTextStyles) {
        textStyle.fStyle.setBackgroundColor(paint);
    }
}

TArray<TextIndex> ParagraphImpl::countSurroundingGraphemes(TextRange textRange) const {
    textRange = textRange.intersection({0, fText.size()});
    TArray<TextIndex> graphemes;
    if ((fCodeUnitProperties[textRange.start] & SkUnicode::CodeUnitFlags::kGraphemeStart) == 0) {
        // Count the previous partial grapheme
        graphemes.emplace_back(textRange.start);
    }
    for (auto index = textRange.start; index < textRange.end; ++index) {
        if ((fCodeUnitProperties[index] & SkUnicode::CodeUnitFlags::kGraphemeStart) != 0) {
            graphemes.emplace_back(index);
        }
    }
    return graphemes;
}

TextIndex ParagraphImpl::findPreviousGraphemeBoundary(TextIndex utf8) const {
    while (utf8 > 0 &&
          (fCodeUnitProperties[utf8] & SkUnicode::CodeUnitFlags::kGraphemeStart) == 0) {
        --utf8;
    }
    return utf8;
}

TextIndex ParagraphImpl::findNextGraphemeBoundary(TextIndex utf8) const {
    while (utf8 < fText.size() &&
          (fCodeUnitProperties[utf8] & SkUnicode::CodeUnitFlags::kGraphemeStart) == 0) {
        ++utf8;
    }
    return utf8;
}

TextIndex ParagraphImpl::findNextGlyphClusterBoundary(TextIndex utf8) const {
    while (utf8 < fText.size() &&
          (fCodeUnitProperties[utf8] & SkUnicode::CodeUnitFlags::kGlyphClusterStart) == 0) {
        ++utf8;
    }
    return utf8;
}

TextIndex ParagraphImpl::findPreviousGlyphClusterBoundary(TextIndex utf8) const {
    while (utf8 > 0 &&
          (fCodeUnitProperties[utf8] & SkUnicode::CodeUnitFlags::kGlyphClusterStart) == 0) {
        --utf8;
    }
    return utf8;
}

void ParagraphImpl::ensureUTF16Mapping() {
    fillUTF16MappingOnce([&] {
        SkUnicode::extractUtfConversionMapping(
                this->text(),
                [&](size_t index) { fUTF8IndexForUTF16Index.emplace_back(index); },
                [&](size_t index) { fUTF16IndexForUTF8Index.emplace_back(index); });
    });
}

void ParagraphImpl::visit(const Visitor& visitor) {
    int lineNumber = 0;
    for (auto& line : fLines) {
        line.ensureTextBlobCachePopulated();
        for (auto& rec : line.fTextBlobCache) {
            if (rec.fBlob == nullptr) {
                continue;
            }
            SkTextBlob::Iter iter(*rec.fBlob);
            SkTextBlob::Iter::ExperimentalRun run;

            STArray<128, uint32_t> clusterStorage;
            const Run* R = rec.fVisitor_Run;
            const uint32_t* clusterPtr = &R->fClusterIndexes[0];

            if (R->fClusterStart > 0) {
                int count = R->fClusterIndexes.size();
                clusterStorage.reset(count);
                for (int i = 0; i < count; ++i) {
                    clusterStorage[i] = R->fClusterStart + R->fClusterIndexes[i];
                }
                clusterPtr = &clusterStorage[0];
            }
            clusterPtr += rec.fVisitor_Pos;

            while (iter.experimentalNext(&run)) {
                const Paragraph::VisitorInfo info = {
                    run.font,
                    rec.fOffset,
                    rec.fClipRect.fRight,
                    run.count,
                    run.glyphs,
                    run.positions,
                    clusterPtr,
                    0,  // flags
                };
                visitor(lineNumber, &info);
                clusterPtr += run.count;
            }
        }
        visitor(lineNumber, nullptr);   // signal end of line
        lineNumber += 1;
    }
}

int ParagraphImpl::getLineNumberAt(TextIndex codeUnitIndex) const {
    if (codeUnitIndex >= fText.size()) {
        return -1;
    }
    size_t startLine = 0;
    size_t endLine = fLines.size() - 1;
    if (fLines.empty() || fLines[endLine].textWithNewlines().end <= codeUnitIndex) {
        return -1;
    }

    while (endLine > startLine) {
        // startLine + 1 <= endLine, so we have startLine <= midLine <= endLine - 1.
        const size_t midLine = (endLine + startLine) / 2;
        const TextRange midLineRange = fLines[midLine].textWithNewlines();
        if (codeUnitIndex < midLineRange.start) {
            endLine = midLine - 1;
        } else if (midLineRange.end <= codeUnitIndex) {
            startLine = midLine + 1;
        } else {
            return midLine;
        }
    }
    SkASSERT(startLine == endLine);
    return startLine;
}

int ParagraphImpl::getLineNumberAtUTF16Offset(size_t codeUnitIndex) {
    this->ensureUTF16Mapping();
    if (codeUnitIndex >= SkToSizeT(fUTF8IndexForUTF16Index.size())) {
        return -1;
    }
    const TextIndex utf8 = fUTF8IndexForUTF16Index[codeUnitIndex];
    return getLineNumberAt(utf8);
}

bool ParagraphImpl::getLineMetricsAt(int lineNumber, LineMetrics* lineMetrics) const {
    if (lineNumber < 0 || lineNumber >= fLines.size()) {
        return false;
    }
    auto& line = fLines[lineNumber];
    if (lineMetrics) {
        *lineMetrics = line.getMetrics();
    }
    return true;
}

TextRange ParagraphImpl::getActualTextRange(int lineNumber, bool includeSpaces) const {
    if (lineNumber < 0 || lineNumber >= fLines.size()) {
        return EMPTY_TEXT;
    }
    auto& line = fLines[lineNumber];
    return includeSpaces ? line.text() : line.trimmedText();
}

bool ParagraphImpl::getGlyphClusterAt(TextIndex codeUnitIndex, GlyphClusterInfo* glyphInfo) {
    const int lineNumber = getLineNumberAt(codeUnitIndex);
    if (lineNumber == -1) {
        return false;
    }
    auto& line = fLines[lineNumber];
    for (auto c = line.clustersWithSpaces().start; c < line.clustersWithSpaces().end; ++c) {
        auto& cluster = fClusters[c];
        if (cluster.contains(codeUnitIndex)) {
            std::vector<TextBox> boxes;
            line.getRectsForRange(cluster.textRange(),
                                    RectHeightStyle::kTight,
                                    RectWidthStyle::kTight,
                                    boxes);
            if (!boxes.empty()) {
                if (glyphInfo) {
                    *glyphInfo = {boxes[0].rect, cluster.textRange(), boxes[0].direction};
                }
                return true;
            }
        }
    }
    return false;
}

bool ParagraphImpl::getClosestGlyphClusterAt(SkScalar dx,
                                             SkScalar dy,
                                             GlyphClusterInfo* glyphInfo) {
    const PositionWithAffinity res = this->getGlyphPositionAtCoordinate(dx, dy);
    SkASSERT(res.position != 0 || res.affinity != Affinity::kUpstream);
    const size_t utf16Offset = res.position + (res.affinity == Affinity::kDownstream ? 0 : -1);
    this->ensureUTF16Mapping();
    SkASSERT(utf16Offset < SkToSizeT(fUTF8IndexForUTF16Index.size()));
    return this->getGlyphClusterAt(fUTF8IndexForUTF16Index[utf16Offset], glyphInfo);
}

bool ParagraphImpl::getGlyphInfoAtUTF16Offset(size_t codeUnitIndex, GlyphInfo* glyphInfo) {
    this->ensureUTF16Mapping();
    if (codeUnitIndex >= SkToSizeT(fUTF8IndexForUTF16Index.size())) {
        return false;
    }
    const TextIndex utf8 = fUTF8IndexForUTF16Index[codeUnitIndex];
    const int lineNumber = getLineNumberAt(utf8);
    if (lineNumber == -1) {
        return false;
    }
    if (glyphInfo == nullptr) {
        return true;
    }
    const TextLine& line = fLines[lineNumber];
    const TextIndex startIndex = findPreviousGraphemeBoundary(utf8);
    const TextIndex endIndex = findNextGraphemeBoundary(utf8 + 1);
    const ClusterIndex glyphClusterIndex = clusterIndex(utf8);
    const Cluster& glyphCluster = cluster(glyphClusterIndex);

    // `startIndex` and `endIndex` must be on the same line.
    std::vector<TextBox> boxes;
    line.getRectsForRange({startIndex, endIndex}, RectHeightStyle::kTight, RectWidthStyle::kTight, boxes);
    // TODO: currently placeholders with height=0 and width=0 are ignored so boxes
    // can be empty. These placeholders should still be reported for their
    // offset information.
    if (glyphInfo && !boxes.empty()) {
        *glyphInfo = {
            boxes[0].rect,
            { fUTF16IndexForUTF8Index[startIndex], fUTF16IndexForUTF8Index[endIndex] },
            boxes[0].direction,
            glyphCluster.run().isEllipsis(),
        };
    }
    return true;
}

bool ParagraphImpl::getClosestUTF16GlyphInfoAt(SkScalar dx, SkScalar dy, GlyphInfo* glyphInfo) {
    const PositionWithAffinity res = this->getGlyphPositionAtCoordinate(dx, dy);
    SkASSERT(res.position != 0 || res.affinity != Affinity::kUpstream);
    const size_t utf16Offset = res.position + (res.affinity == Affinity::kDownstream ? 0 : -1);
    return getGlyphInfoAtUTF16Offset(utf16Offset, glyphInfo);
}

SkFont ParagraphImpl::getFontAt(TextIndex codeUnitIndex) const {
    for (auto& run : fRuns) {
        const auto textRange = run.textRange();
        if (textRange.start <= codeUnitIndex && codeUnitIndex < textRange.end) {
            return run.font();
        }
    }
    return SkFont();
}

SkFont ParagraphImpl::getFontAtUTF16Offset(size_t codeUnitIndex) {
    ensureUTF16Mapping();
    if (codeUnitIndex >= SkToSizeT(fUTF8IndexForUTF16Index.size())) {
        return SkFont();
    }
    const TextIndex utf8 = fUTF8IndexForUTF16Index[codeUnitIndex];
    for (auto& run : fRuns) {
        const auto textRange = run.textRange();
        if (textRange.start <= utf8 && utf8 < textRange.end) {
            return run.font();
        }
    }
    return SkFont();
}

std::vector<Paragraph::FontInfo> ParagraphImpl::getFonts() const {
    std::vector<FontInfo> results;
    for (auto& run : fRuns) {
        results.emplace_back(run.font(), run.textRange());
    }
    return results;
}

void ParagraphImpl::extendedVisit(const ExtendedVisitor& visitor) {
    int lineNumber = 0;
    for (auto& line : fLines) {
        line.iterateThroughVisualRuns(
            false,
            [&](const Run* run,
                SkScalar runOffsetInLine,
                TextRange textRange,
                SkScalar* runWidthInLine) {
                *runWidthInLine = line.iterateThroughSingleRunByStyles(
                TextLine::TextAdjustment::GlyphCluster,
                run,
                runOffsetInLine,
                textRange,
                StyleType::kNone,
                [&](TextRange textRange,
                    const TextStyle& style,
                    const TextLine::ClipContext& context) {
                    SkScalar correctedBaseline = SkScalarFloorToScalar(
                        line.baseline() + style.getBaselineShift() + 0.5);
                    SkPoint offset =
                        SkPoint::Make(line.offset().fX + context.fTextShift,
                                      line.offset().fY + correctedBaseline);
                    SkRect rect = context.clip.makeOffset(line.offset());
                    AutoSTArray<16, SkRect> glyphBounds;
                    glyphBounds.reset(SkToInt(run->size()));
                    run->font().getBounds(run->glyphs(), glyphBounds, nullptr);
                    STArray<128, uint32_t> clusterStorage;
                    const uint32_t* clusterPtr = run->clusterIndexes().data();
                    if (run->fClusterStart > 0) {
                        clusterStorage.reset(context.size);
                        for (size_t i = 0; i < context.size; ++i) {
                          clusterStorage[i] =
                              run->fClusterStart + run->fClusterIndexes[i];
                        }
                        clusterPtr = &clusterStorage[0];
                    }
                    const Paragraph::ExtendedVisitorInfo info = {
                        run->font(),
                        offset,
                        SkSize::Make(rect.width(), rect.height()),
                        SkToS16(context.size),
                        &run->glyphs()[context.pos],
                        &run->fPositions[context.pos],
                        &glyphBounds[context.pos],
                        clusterPtr,
                        0,  // flags
                    };
                    visitor(lineNumber, &info);
                });
            return true;
            });
        visitor(lineNumber, nullptr);   // signal end of line
        lineNumber += 1;
    }
}

int ParagraphImpl::getPath(int lineNumber, SkPath* dest) {
    SkPathBuilder builder;
    int notConverted = 0;
    auto& line = fLines[lineNumber];
    line.iterateThroughVisualRuns(
              false,
              [&](const Run* run,
                  SkScalar runOffsetInLine,
                  TextRange textRange,
                  SkScalar* runWidthInLine) {
          *runWidthInLine = line.iterateThroughSingleRunByStyles(
          TextLine::TextAdjustment::GlyphCluster,
          run,
          runOffsetInLine,
          textRange,
          StyleType::kNone,
          [&](TextRange textRange,
              const TextStyle& style,
              const TextLine::ClipContext& context) {
              const SkFont& font = run->font();
              SkScalar correctedBaseline = SkScalarFloorToScalar(
                line.baseline() + style.getBaselineShift() + 0.5);
              SkPoint offset =
                  SkPoint::Make(line.offset().fX + context.fTextShift,
                                line.offset().fY + correctedBaseline);
              SkRect rect = context.clip.makeOffset(offset);
              struct Rec {
                  SkPathBuilder* fBuilder;
                  SkPoint fOffset;
                  const SkPoint* fPos;
                  int fNotConverted;
              } rec =
                  {&builder, SkPoint::Make(rect.left(), rect.top()), &run->positions()[context.pos], 0};
              font.getPaths({&run->glyphs()[context.pos], context.size},
                    [](const SkPath* path, const SkMatrix& mx, void* ctx) {
                        Rec* rec = reinterpret_cast<Rec*>(ctx);
                        if (path) {
                            SkMatrix total = mx;
                            total.postTranslate(rec->fPos->fX + rec->fOffset.fX,
                                                rec->fPos->fY + rec->fOffset.fY);
                            rec->fBuilder->addPath(*path, total);
                        } else {
                            rec->fNotConverted++;
                        }
                        rec->fPos += 1; // move to the next glyph's position
                    }, &rec);
              notConverted += rec.fNotConverted;
          });
        *dest = builder.detach();
        return true;
    });

    return notConverted;
}

SkPath Paragraph::GetPath(SkTextBlob* textBlob) {
    SkPathBuilder builder;
    SkTextBlobRunIterator iter(textBlob);
    while (!iter.done()) {
        SkFont font = iter.font();
        struct Rec { SkPathBuilder* fBuilder; SkPoint fOffset; const SkPoint* fPos; } rec =
            {&builder, {textBlob->bounds().left(), textBlob->bounds().top()},
             iter.points()};
        font.getPaths({iter.glyphs(), iter.glyphCount()},
            [](const SkPath* src, const SkMatrix& mx, void* ctx) {
                Rec* rec = (Rec*)ctx;
                if (src) {
                    SkMatrix tmp(mx);
                    tmp.postTranslate(rec->fPos->fX - rec->fOffset.fX,
                                      rec->fPos->fY - rec->fOffset.fY);
                    rec->fBuilder->addPath(*src, tmp);
                }
                rec->fPos += 1;
            },
            &rec);
        iter.next();
    }
    return builder.detach();
}

bool ParagraphImpl::containsEmoji(SkTextBlob* textBlob) {
    bool result = false;
    SkTextBlobRunIterator iter(textBlob);
    while (!iter.done() && !result) {
        // Walk through all the text by codepoints
        this->getUnicode()->forEachCodepoint(iter.text(), iter.textSize(),
           [&](SkUnichar unichar, int32_t start, int32_t end, int32_t count) {
                if (this->getUnicode()->isEmoji(unichar)) {
                    result = true;
                }
            });
        iter.next();
    }
    return result;
}

bool ParagraphImpl::containsColorFontOrBitmap(SkTextBlob* textBlob) {
    SkTextBlobRunIterator iter(textBlob);
    bool flag = false;
    while (!iter.done() && !flag) {
        iter.font().getPaths(
            {(const SkGlyphID*) iter.glyphs(), iter.glyphCount()},
            [](const SkPath* path, const SkMatrix& mx, void* ctx) {
                if (path == nullptr) {
                    bool* flag1 = (bool*)ctx;
                    *flag1 = true;
                }
            }, &flag);
        iter.next();
    }
    return flag;
}

}  // namespace textlayout
}  // namespace skia
