// Copyright 2019 Google LLC.

#include "modules/skparagraph/src/Iterators.h"
#include "modules/skparagraph/src/OneLineShaper.h"
#include "src/base/SkUTF.h"
#include <algorithm>
#include <unordered_set>

static inline SkUnichar nextUtf8Unit(const char** ptr, const char* end) {
    SkUnichar val = SkUTF::NextUTF8(ptr, end);
    return val < 0 ? 0xFFFD : val;
}

namespace skia {
namespace textlayout {

void OneLineShaper::commitRunBuffer(const RunInfo&) {

    fCurrentRun->commit();

    auto oldUnresolvedCount = fUnresolvedBlocks.size();
/*
    SkDebugf("Run [%zu:%zu)\n", fCurrentRun->fTextRange.start, fCurrentRun->fTextRange.end);
    for (size_t i = 0; i < fCurrentRun->size(); ++i) {
        SkDebugf("[%zu] %hu %u %f\n", i, fCurrentRun->fGlyphs[i], fCurrentRun->fClusterIndexes[i], fCurrentRun->fPositions[i].fX);
    }
*/
    // Find all unresolved blocks
    sortOutGlyphs([&](GlyphRange block){
        if (block.width() == 0) {
            return;
        }
        addUnresolvedWithRun(block);
    });

    // Fill all the gaps between unresolved blocks with resolved ones
    if (oldUnresolvedCount == fUnresolvedBlocks.size()) {
        // No unresolved blocks added - we resolved the block with one run entirely
        addFullyResolved();
        return;
    } else if (oldUnresolvedCount == fUnresolvedBlocks.size() - 1) {
        auto& unresolved = fUnresolvedBlocks.back();
        if (fCurrentRun->textRange() == unresolved.fText) {
            // Nothing was resolved; preserve the initial run if it makes sense
            auto& front = fUnresolvedBlocks.front();
            if (front.fRun != nullptr) {
               unresolved.fRun = front.fRun;
               unresolved.fGlyphs = front.fGlyphs;
            }
            return;
        }
    }

    fillGaps(oldUnresolvedCount);
}

#ifdef SK_DEBUG
void OneLineShaper::printState() {
    SkDebugf("Resolved: %zu\n", fResolvedBlocks.size());
    for (auto& resolved : fResolvedBlocks) {
        if (resolved.fRun ==  nullptr) {
            SkDebugf("[%zu:%zu) unresolved\n",
                    resolved.fText.start, resolved.fText.end);
            continue;
        }
        SkString name("???");
        if (resolved.fRun->fFont.getTypeface() != nullptr) {
            resolved.fRun->fFont.getTypeface()->getFamilyName(&name);
        }
        SkDebugf("[%zu:%zu) ", resolved.fGlyphs.start, resolved.fGlyphs.end);
        SkDebugf("[%zu:%zu) with %s\n",
                resolved.fText.start, resolved.fText.end,
                name.c_str());
    }

    auto size = fUnresolvedBlocks.size();
    SkDebugf("Unresolved: %zu\n", size);
    for (const auto& unresolved : fUnresolvedBlocks) {
        SkDebugf("[%zu:%zu)\n", unresolved.fText.start, unresolved.fText.end);
    }
}
#endif

void OneLineShaper::fillGaps(size_t startingCount) {
    // Fill out gaps between all unresolved blocks
    TextRange resolvedTextLimits = fCurrentRun->fTextRange;
    if (!fCurrentRun->leftToRight()) {
        std::swap(resolvedTextLimits.start, resolvedTextLimits.end);
    }
    TextIndex resolvedTextStart = resolvedTextLimits.start;
    GlyphIndex resolvedGlyphsStart = 0;

    auto begin = fUnresolvedBlocks.begin();
    auto end = fUnresolvedBlocks.end();
    begin += startingCount; // Skip the old ones, do the new ones
    TextRange prevText = EMPTY_TEXT;
    for (; begin != end; ++begin) {
        auto& unresolved = *begin;

        if (unresolved.fText == prevText) {
            // Clean up repetitive blocks that appear inside the same grapheme block
            unresolved.fText = EMPTY_TEXT;
            continue;
        } else {
            prevText = unresolved.fText;
        }

        TextRange resolvedText(resolvedTextStart, fCurrentRun->leftToRight() ? unresolved.fText.start : unresolved.fText.end);
        if (resolvedText.width() > 0) {
            if (!fCurrentRun->leftToRight()) {
                std::swap(resolvedText.start, resolvedText.end);
            }

            GlyphRange resolvedGlyphs(resolvedGlyphsStart, unresolved.fGlyphs.start);
            RunBlock resolved(fCurrentRun, resolvedText, resolvedGlyphs, resolvedGlyphs.width());

            if (resolvedGlyphs.width() == 0) {
                // Extend the unresolved block with an empty resolved
                if (unresolved.fText.end <= resolved.fText.start) {
                    unresolved.fText.end = resolved.fText.end;
                }
                if (unresolved.fText.start >= resolved.fText.end) {
                    unresolved.fText.start = resolved.fText.start;
                }
            } else {
                fResolvedBlocks.emplace_back(resolved);
            }
        }
        resolvedGlyphsStart = unresolved.fGlyphs.end;
        resolvedTextStart =  fCurrentRun->leftToRight()
                                ? unresolved.fText.end
                                : unresolved.fText.start;
    }

    TextRange resolvedText(resolvedTextStart,resolvedTextLimits.end);
    if (resolvedText.width() > 0) {
        if (!fCurrentRun->leftToRight()) {
            std::swap(resolvedText.start, resolvedText.end);
        }

        GlyphRange resolvedGlyphs(resolvedGlyphsStart, fCurrentRun->size());
        RunBlock resolved(fCurrentRun, resolvedText, resolvedGlyphs, resolvedGlyphs.width());
        fResolvedBlocks.emplace_back(resolved);
    }
}

void OneLineShaper::finish(const Block& block, SkScalar height, SkScalar& advanceX) {
    auto blockText = block.fRange;

    // Add all unresolved blocks to resolved blocks
    while (!fUnresolvedBlocks.empty()) {
        auto unresolved = fUnresolvedBlocks.front();
        fUnresolvedBlocks.pop_front();
        if (unresolved.fText.width() == 0) {
            continue;
        }
        fResolvedBlocks.emplace_back(unresolved);
        fUnresolvedGlyphs += unresolved.fGlyphs.width();
    }

    // Sort all pieces by text
    std::sort(fResolvedBlocks.begin(), fResolvedBlocks.end(),
              [](const RunBlock& a, const RunBlock& b) {
                return a.fText.start < b.fText.start;
              });

    // Go through all of them
    size_t lastTextEnd = blockText.start;
    for (auto& resolvedBlock : fResolvedBlocks) {

        if (resolvedBlock.fText.end <= blockText.start) {
            continue;
        }

        if (resolvedBlock.fRun != nullptr) {
            fParagraph->fFontSwitches.emplace_back(resolvedBlock.fText.start, resolvedBlock.fRun->fFont);
        }

        auto run = resolvedBlock.fRun;
        auto glyphs = resolvedBlock.fGlyphs;
        auto text = resolvedBlock.fText;
        if (lastTextEnd != text.start) {
            SkDEBUGF("Text ranges mismatch: ...:%zu] - [%zu:%zu] (%zu-%zu)\n",
                     lastTextEnd, text.start, text.end,  glyphs.start, glyphs.end);
            SkASSERT(false);
        }
        lastTextEnd = text.end;

        if (resolvedBlock.isFullyResolved()) {
            // Just move the entire run
            resolvedBlock.fRun->fIndex = this->fParagraph->fRuns.size();
            this->fParagraph->fRuns.emplace_back(*resolvedBlock.fRun);
            resolvedBlock.fRun.reset();
            continue;
        } else if (run == nullptr) {
            continue;
        }

        auto runAdvance = SkVector::Make(run->posX(glyphs.end) - run->posX(glyphs.start), run->fAdvance.fY);
        const SkShaper::RunHandler::RunInfo info = {
                run->fFont,
                run->fBidiLevel,
                runAdvance,
                glyphs.width(),
                SkShaper::RunHandler::Range(text.start - run->fClusterStart, text.width())
        };
        this->fParagraph->fRuns.emplace_back(
                    this->fParagraph,
                    info,
                    run->fClusterStart,
                    height,
                    block.fStyle.getHalfLeading(),
                    block.fStyle.getBaselineShift(),
                    this->fParagraph->fRuns.size(),
                    advanceX
                );
        auto piece = &this->fParagraph->fRuns.back();

        // TODO: Optimize copying
        SkPoint zero = {run->fPositions[glyphs.start].fX, 0};
        for (size_t i = glyphs.start; i <= glyphs.end; ++i) {

            auto index = i - glyphs.start;
            if (i < glyphs.end) {
                piece->fGlyphs[index] = run->fGlyphs[i];
            }
            piece->fClusterIndexes[index] = run->fClusterIndexes[i];
            piece->fPositions[index] = run->fPositions[i] - zero;
            piece->fOffsets[index] = run->fOffsets[i];
            piece->addX(index, advanceX);
        }

        // Carve out the line text out of the entire run text
        fAdvance.fX += runAdvance.fX;
        fAdvance.fY = std::max(fAdvance.fY, runAdvance.fY);
    }

    advanceX = fAdvance.fX;
    if (lastTextEnd != blockText.end) {
        SkDEBUGF("Last range mismatch: %zu - %zu\n", lastTextEnd, blockText.end);
        SkASSERT(false);
    }
}

// Make it [left:right) regardless of a text direction
TextRange OneLineShaper::normalizeTextRange(GlyphRange glyphRange) {

    if (fCurrentRun->leftToRight()) {
        return TextRange(clusterIndex(glyphRange.start), clusterIndex(glyphRange.end));
    } else {
        return TextRange(clusterIndex(glyphRange.end - 1),
                glyphRange.start > 0
                ? clusterIndex(glyphRange.start - 1)
                : fCurrentRun->fTextRange.end);
    }
}

void OneLineShaper::addFullyResolved() {
    if (this->fCurrentRun->size() == 0) {
        return;
    }
    RunBlock resolved(fCurrentRun,
                      this->fCurrentRun->fTextRange,
                      GlyphRange(0, this->fCurrentRun->size()),
                      this->fCurrentRun->size());
    fResolvedBlocks.emplace_back(resolved);
}

void OneLineShaper::addUnresolvedWithRun(GlyphRange glyphRange) {
    auto extendedText = this->clusteredText(glyphRange); // It also modifies glyphRange if needed
    RunBlock unresolved(fCurrentRun, extendedText, glyphRange, 0);
    if (unresolved.fGlyphs.width() == fCurrentRun->size()) {
        SkASSERT(unresolved.fText.width() == fCurrentRun->fTextRange.width());
    } else if (fUnresolvedBlocks.size() > 0) {
        auto& lastUnresolved = fUnresolvedBlocks.back();
        if (lastUnresolved.fRun != nullptr &&
            lastUnresolved.fRun->fIndex == fCurrentRun->fIndex) {

            if (lastUnresolved.fText.end == unresolved.fText.start) {
              // Two pieces next to each other - can join them
              lastUnresolved.fText.end = unresolved.fText.end;
              lastUnresolved.fGlyphs.end = glyphRange.end;
              return;
            } else if(lastUnresolved.fText == unresolved.fText) {
                // Nothing was resolved; ignore it
                return;
            } else if (lastUnresolved.fText.contains(unresolved.fText)) {
                // We get here for the very first unresolved piece
                return;
            } else if (lastUnresolved.fText.intersects(unresolved.fText)) {
                // Few pieces of the same unresolved text block can ignore the second one
                lastUnresolved.fGlyphs.start = std::min(lastUnresolved.fGlyphs.start, glyphRange.start);
                lastUnresolved.fGlyphs.end = std::max(lastUnresolved.fGlyphs.end, glyphRange.end);
                lastUnresolved.fText = this->clusteredText(lastUnresolved.fGlyphs);
                return;
            }
        }
    }
    fUnresolvedBlocks.emplace_back(unresolved);
}

// Glue whitespaces to the next/prev unresolved blocks
// (so we don't have chinese text with english whitespaces broken into millions of tiny runs)
void OneLineShaper::sortOutGlyphs(std::function<void(GlyphRange)>&& sortOutUnresolvedBLock) {

    GlyphRange block = EMPTY_RANGE;
    bool graphemeResolved = false;
    TextIndex graphemeStart = EMPTY_INDEX;
    for (size_t i = 0; i < fCurrentRun->size(); ++i) {

        ClusterIndex ci = clusterIndex(i);
        // Removing all pretty optimizations for whitespaces
        // because they get in a way of grapheme rounding
        // Inspect the glyph
        auto glyph = fCurrentRun->fGlyphs[i];

        GraphemeIndex gi = fParagraph->findPreviousGraphemeBoundary(ci);
        if ((fCurrentRun->leftToRight() ? gi > graphemeStart : gi < graphemeStart) || graphemeStart == EMPTY_INDEX) {
            // This is the Flutter change
            // Do not count control codepoints as unresolved
            bool isControl8 = fParagraph->codeUnitHasProperty(ci,
                                                              SkUnicode::CodeUnitFlags::kControl);
            // We only count glyph resolved if all the glyphs in its grapheme are resolved
            graphemeResolved = glyph != 0 || isControl8;
            graphemeStart = gi;
        } else if (glyph == 0) {
            // Found unresolved glyph - the entire grapheme is unresolved now
            graphemeResolved = false;
        }

        if (!graphemeResolved) { // Unresolved glyph and not control codepoint
            if (block.start == EMPTY_INDEX) {
                // Start new unresolved block
                block.start = i;
                block.end = EMPTY_INDEX;
            } else {
                // Keep skipping unresolved block
            }
        } else { // Resolved glyph or control codepoint
            if (block.start == EMPTY_INDEX) {
                // Keep skipping resolved code points
            } else {
                // This is the end of unresolved block
                block.end = i;
                sortOutUnresolvedBLock(block);
                block = EMPTY_RANGE;
            }
        }
    }

    // One last block could have been left
    if (block.start != EMPTY_INDEX) {
        block.end = fCurrentRun->size();
        sortOutUnresolvedBLock(block);
    }
}

void OneLineShaper::iterateThroughFontStyles(TextRange textRange,
                                             SkSpan<Block> styleSpan,
                                             const ShapeSingleFontVisitor& visitor) {
    Block combinedBlock;
    SkTArray<SkShaper::Feature> features;

    auto addFeatures = [&features](const Block& block) {
        for (auto& ff : block.fStyle.getFontFeatures()) {
            if (ff.fName.size() != 4) {
                SkDEBUGF("Incorrect font feature: %s=%d\n", ff.fName.c_str(), ff.fValue);
                continue;
            }
            SkShaper::Feature feature = {
                SkSetFourByteTag(ff.fName[0], ff.fName[1], ff.fName[2], ff.fName[3]),
                SkToU32(ff.fValue),
                block.fRange.start,
                block.fRange.end
            };
            features.emplace_back(feature);
        }
        // Disable ligatures if letter spacing is enabled.
        if (block.fStyle.getLetterSpacing() > 0) {
            features.emplace_back(SkShaper::Feature{
                SkSetFourByteTag('l', 'i', 'g', 'a'), 0, block.fRange.start, block.fRange.end
            });
        }
    };

    for (auto& block : styleSpan) {
        BlockRange blockRange(std::max(block.fRange.start, textRange.start), std::min(block.fRange.end, textRange.end));
        if (blockRange.empty()) {
            continue;
        }
        SkASSERT(combinedBlock.fRange.width() == 0 || combinedBlock.fRange.end == block.fRange.start);

        if (!combinedBlock.fRange.empty()) {
            if (block.fStyle.matchOneAttribute(StyleType::kFont, combinedBlock.fStyle)) {
                combinedBlock.add(blockRange);
                addFeatures(block);
                continue;
            }
            // Resolve all characters in the block for this style
            visitor(combinedBlock, features);
        }

        combinedBlock.fRange = blockRange;
        combinedBlock.fStyle = block.fStyle;
        features.clear();
        addFeatures(block);
    }

    visitor(combinedBlock, features);
#ifdef SK_DEBUG
    //printState();
#endif
}

void OneLineShaper::matchResolvedFonts(const TextStyle& textStyle,
                                       const TypefaceVisitor& visitor) {
    std::vector<sk_sp<SkTypeface>> typefaces = fParagraph->fFontCollection->findTypefaces(textStyle.getFontFamilies(), textStyle.getFontStyle(), textStyle.getFontArguments());

    for (const auto& typeface : typefaces) {
        if (visitor(typeface) == Resolved::Everything) {
            // Resolved everything
            return;
        }
    }

    if (fParagraph->fFontCollection->fontFallbackEnabled()) {
        // Give fallback a clue
        // Some unresolved subblocks might be resolved with different fallback fonts
        std::vector<RunBlock> hopelessBlocks;
        while (!fUnresolvedBlocks.empty()) {
            auto unresolvedRange = fUnresolvedBlocks.front().fText;
            auto unresolvedText = fParagraph->text(unresolvedRange);
            const char* ch = unresolvedText.begin();
            // We have the global cache for all already found typefaces for SkUnichar
            // but we still need to keep track of all SkUnichars used in this unresolved block
            SkTHashSet<SkUnichar> alreadyTriedCodepoints;
            SkTHashSet<SkTypefaceID> alreadyTriedTypefaces;
            while (true) {

                if (ch == unresolvedText.end()) {
                    // Not a single codepoint could be resolved but we finished the block
                    hopelessBlocks.push_back(fUnresolvedBlocks.front());
                    fUnresolvedBlocks.pop_front();
                    break;
                }

                // See if we can switch to the next DIFFERENT codepoint
                SkUnichar unicode = -1;
                while (ch != unresolvedText.end()) {
                    unicode = nextUtf8Unit(&ch, unresolvedText.end());
                    if (!alreadyTriedCodepoints.contains(unicode)) {
                        alreadyTriedCodepoints.add(unicode);
                        break;
                    }
                }
                SkASSERT(unicode != -1);

                // First try to find in in a cache
                sk_sp<SkTypeface> typeface;
                FontKey fontKey(unicode, textStyle.getFontStyle(), textStyle.getLocale());
                auto found = fFallbackFonts.find(fontKey);
                if (found != nullptr) {
                    typeface = *found;
                } else {
                    typeface = fParagraph->fFontCollection->defaultFallback(
                            unicode, textStyle.getFontStyle(), textStyle.getLocale());

                    if (typeface == nullptr) {
                        // There is no fallback font for this character, so move on to the next character.
                        continue;
                    }
                    fFallbackFonts.set(fontKey, typeface);
                }

                // Check if we already tried this font on this text range
                if (!alreadyTriedTypefaces.contains(typeface->uniqueID())) {
                    alreadyTriedTypefaces.add(typeface->uniqueID());
                } else {
                    continue;
                }

                auto resolvedBlocksBefore = fResolvedBlocks.size();
                auto resolved = visitor(typeface);
                if (resolved == Resolved::Everything) {
                    if (hopelessBlocks.empty()) {
                        // Resolved everything, no need to try another font
                        return;
                    } else if (resolvedBlocksBefore < fResolvedBlocks.size()) {
                        // There are some resolved blocks
                        resolved = Resolved::Something;
                    } else {
                        // All blocks are hopeless
                        resolved = Resolved::Nothing;
                    }
                }

                if (resolved == Resolved::Something) {
                    // Resolved something, no need to try another codepoint
                    break;
                }
            }
        }

        // Return hopeless blocks back
        for (auto& block : hopelessBlocks) {
            fUnresolvedBlocks.emplace_front(block);
        }
    }
}

bool OneLineShaper::iterateThroughShapingRegions(const ShapeVisitor& shape) {

    size_t bidiIndex = 0;

    SkScalar advanceX = 0;
    for (auto& placeholder : fParagraph->fPlaceholders) {

        if (placeholder.fTextBefore.width() > 0) {
            // Shape the text by bidi regions
            while (bidiIndex < fParagraph->fBidiRegions.size()) {
                SkUnicode::BidiRegion& bidiRegion = fParagraph->fBidiRegions[bidiIndex];
                auto start = std::max(bidiRegion.start, placeholder.fTextBefore.start);
                auto end = std::min(bidiRegion.end, placeholder.fTextBefore.end);

                // Set up the iterators (the style iterator points to a bigger region that it could
                TextRange textRange(start, end);
                auto blockRange = fParagraph->findAllBlocks(textRange);
                if (!blockRange.empty()) {
                    SkSpan<Block> styleSpan(fParagraph->blocks(blockRange));

                    // Shape the text between placeholders
                    if (!shape(textRange, styleSpan, advanceX, start, bidiRegion.level)) {
                        return false;
                    }
                }

                if (end == bidiRegion.end) {
                    ++bidiIndex;
                } else /*if (end == placeholder.fTextBefore.end)*/ {
                    break;
                }
            }
        }

        if (placeholder.fRange.width() == 0) {
            continue;
        }

        // Get the placeholder font
        std::vector<sk_sp<SkTypeface>> typefaces = fParagraph->fFontCollection->findTypefaces(
            placeholder.fTextStyle.getFontFamilies(),
            placeholder.fTextStyle.getFontStyle(),
            placeholder.fTextStyle.getFontArguments());
        sk_sp<SkTypeface> typeface = typefaces.size() ? typefaces.front() : nullptr;
        SkFont font(typeface, placeholder.fTextStyle.getFontSize());

        // "Shape" the placeholder
        uint8_t bidiLevel = (bidiIndex < fParagraph->fBidiRegions.size())
            ? fParagraph->fBidiRegions[bidiIndex].level
            : 2;
        const SkShaper::RunHandler::RunInfo runInfo = {
            font,
            bidiLevel,
            SkPoint::Make(placeholder.fStyle.fWidth, placeholder.fStyle.fHeight),
            1,
            SkShaper::RunHandler::Range(0, placeholder.fRange.width())
        };
        auto& run = fParagraph->fRuns.emplace_back(this->fParagraph,
                                       runInfo,
                                       placeholder.fRange.start,
                                       0.0f,
                                       0.0f,
                                       false,
                                       fParagraph->fRuns.size(),
                                       advanceX);

        run.fPositions[0] = { advanceX, 0 };
        run.fOffsets[0] = {0, 0};
        run.fClusterIndexes[0] = 0;
        run.fPlaceholderIndex = &placeholder - fParagraph->fPlaceholders.begin();
        advanceX += placeholder.fStyle.fWidth;
    }
    return true;
}

bool OneLineShaper::shape() {

    // The text can be broken into many shaping sequences
    // (by place holders, possibly, by hard line breaks or tabs, too)
    auto limitlessWidth = std::numeric_limits<SkScalar>::max();

    auto result = iterateThroughShapingRegions(
            [this, limitlessWidth]
            (TextRange textRange, SkSpan<Block> styleSpan, SkScalar& advanceX, TextIndex textStart, uint8_t defaultBidiLevel) {

        // Set up the shaper and shape the next
        auto shaper = SkShaper::MakeShapeDontWrapOrReorder(fParagraph->fUnicode->copy());
        if (shaper == nullptr) {
            // For instance, loadICU does not work. We have to stop the process
            return false;
        }

        iterateThroughFontStyles(textRange, styleSpan,
                [this, &shaper, defaultBidiLevel, limitlessWidth, &advanceX]
                (Block block, SkTArray<SkShaper::Feature> features) {
            auto blockSpan = SkSpan<Block>(&block, 1);

            // Start from the beginning (hoping that it's a simple case one block - one run)
            fHeight = block.fStyle.getHeightOverride() ? block.fStyle.getHeight() : 0;
            fUseHalfLeading = block.fStyle.getHalfLeading();
            fBaselineShift = block.fStyle.getBaselineShift();
            fAdvance = SkVector::Make(advanceX, 0);
            fCurrentText = block.fRange;
            fUnresolvedBlocks.emplace_back(RunBlock(block.fRange));

            this->matchResolvedFonts(block.fStyle, [&](sk_sp<SkTypeface> typeface) {

                // Create one more font to try
                SkFont font(std::move(typeface), block.fStyle.getFontSize());
                font.setEdging(SkFont::Edging::kAntiAlias);
                font.setHinting(SkFontHinting::kSlight);
                font.setSubpixel(true);

                // Apply fake bold and/or italic settings to the font if the
                // typeface's attributes do not match the intended font style.
                int wantedWeight = block.fStyle.getFontStyle().weight();
                bool fakeBold =
                    wantedWeight >= SkFontStyle::kSemiBold_Weight &&
                    wantedWeight - font.getTypeface()->fontStyle().weight() >= 200;
                bool fakeItalic =
                    block.fStyle.getFontStyle().slant() == SkFontStyle::kItalic_Slant &&
                    font.getTypeface()->fontStyle().slant() != SkFontStyle::kItalic_Slant;
                font.setEmbolden(fakeBold);
                font.setSkewX(fakeItalic ? -SK_Scalar1 / 4 : 0);

                // Walk through all the currently unresolved blocks
                // (ignoring those that appear later)
                auto resolvedCount = fResolvedBlocks.size();
                auto unresolvedCount = fUnresolvedBlocks.size();
                while (unresolvedCount-- > 0) {
                    auto unresolvedRange = fUnresolvedBlocks.front().fText;
                    if (unresolvedRange == EMPTY_TEXT) {
                        // Duplicate blocks should be ignored
                        fUnresolvedBlocks.pop_front();
                        continue;
                    }
                    auto unresolvedText = fParagraph->text(unresolvedRange);

                    SkShaper::TrivialFontRunIterator fontIter(font, unresolvedText.size());
                    LangIterator langIter(unresolvedText, blockSpan,
                                      fParagraph->paragraphStyle().getTextStyle());
                    SkShaper::TrivialBiDiRunIterator bidiIter(defaultBidiLevel, unresolvedText.size());
                    auto scriptIter = SkShaper::MakeSkUnicodeHbScriptRunIterator(
                            unresolvedText.begin(), unresolvedText.size());
                    fCurrentText = unresolvedRange;

                    // Map the block's features to subranges within the unresolved range.
                    SkTArray<SkShaper::Feature> adjustedFeatures(features.size());
                    for (const SkShaper::Feature& feature : features) {
                        SkRange<size_t> featureRange(feature.start, feature.end);
                        if (unresolvedRange.intersects(featureRange)) {
                            SkRange<size_t> adjustedRange = unresolvedRange.intersection(featureRange);
                            adjustedRange.Shift(-static_cast<std::make_signed_t<size_t>>(unresolvedRange.start));
                            adjustedFeatures.push_back({feature.tag, feature.value, adjustedRange.start, adjustedRange.end});
                        }
                    }

                    shaper->shape(unresolvedText.begin(), unresolvedText.size(),
                            fontIter, bidiIter,*scriptIter, langIter,
                            adjustedFeatures.data(), adjustedFeatures.size(),
                            limitlessWidth, this);

                    // Take off the queue the block we tried to resolved -
                    // whatever happened, we have now smaller pieces of it to deal with
                    fUnresolvedBlocks.pop_front();
                }

                if (fUnresolvedBlocks.empty()) {
                    // In some cases it does not mean everything
                    // (when we excluded some hopeless blocks from the list)
                    return Resolved::Everything;
                } else if (resolvedCount < fResolvedBlocks.size()) {
                    return Resolved::Something;
                } else {
                    return Resolved::Nothing;
                }
            });

            this->finish(block, fHeight, advanceX);
        });

        return true;
    });

    return result;
}

// When we extend TextRange to the grapheme edges, we also extend glyphs range
TextRange OneLineShaper::clusteredText(GlyphRange& glyphs) {

    enum class Dir { left, right };
    enum class Pos { inclusive, exclusive };

    // [left: right)
    auto findBaseChar = [&](TextIndex index, Dir dir) -> TextIndex {

        if (dir == Dir::right) {
            while (index < fCurrentRun->fTextRange.end) {
                if (this->fParagraph->codeUnitHasProperty(index,
                                                      SkUnicode::CodeUnitFlags::kGraphemeStart)) {
                    return index;
                }
                ++index;
            }
            return fCurrentRun->fTextRange.end;
        } else {
            while (index > fCurrentRun->fTextRange.start) {
                if (this->fParagraph->codeUnitHasProperty(index,
                                                      SkUnicode::CodeUnitFlags::kGraphemeStart)) {
                    return index;
                }
                --index;
            }
            return fCurrentRun->fTextRange.start;
        }
    };

    TextRange textRange(normalizeTextRange(glyphs));
    textRange.start = findBaseChar(textRange.start, Dir::left);
    textRange.end = findBaseChar(textRange.end, Dir::right);

    // Correct the glyphRange in case we extended the text to the grapheme edges
    // TODO: code it without if (as a part of LTR/RTL refactoring)
    if (fCurrentRun->leftToRight()) {
        while (glyphs.start > 0 && clusterIndex(glyphs.start) > textRange.start) {
          glyphs.start--;
        }
        while (glyphs.end < fCurrentRun->size() && clusterIndex(glyphs.end) < textRange.end) {
          glyphs.end++;
        }
    } else {
        while (glyphs.start > 0 && clusterIndex(glyphs.start - 1) < textRange.end) {
          glyphs.start--;
        }
        while (glyphs.end < fCurrentRun->size() && clusterIndex(glyphs.end) > textRange.start) {
          glyphs.end++;
        }
    }

    return { textRange.start, textRange.end };
}

bool OneLineShaper::FontKey::operator==(const OneLineShaper::FontKey& other) const {
    return fUnicode == other.fUnicode && fFontStyle == other.fFontStyle && fLocale == other.fLocale;
}

size_t OneLineShaper::FontKey::Hasher::operator()(const OneLineShaper::FontKey& key) const {

    return SkGoodHash()(key.fUnicode) ^
           SkGoodHash()(key.fFontStyle) ^
           SkGoodHash()(key.fLocale.c_str());
}

}  // namespace textlayout
}  // namespace skia
