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

#ifndef SkFindAndPositionGlyph_DEFINED
#define SkFindAndPositionGlyph_DEFINED

#include "SkArenaAlloc.h"
#include "SkAutoKern.h"
#include "SkGlyph.h"
#include "SkGlyphCache.h"
#include "SkMatrixPriv.h"
#include "SkPaint.h"
#include "SkTemplates.h"
#include "SkUtils.h"
#include <utility>

class SkFindAndPlaceGlyph {
public:
    template<typename ProcessOneGlyph>
    static void ProcessText(
        SkPaint::TextEncoding, const char text[], size_t byteLength,
        SkPoint offset, const SkMatrix& matrix, SkPaint::Align textAlignment,
        SkGlyphCache* cache, ProcessOneGlyph&& processOneGlyph);
    // ProcessPosText handles all cases for finding and positioning glyphs. It has a very large
    // multiplicity. It figures out the glyph, position and rounding and pass those parameters to
    // processOneGlyph.
    //
    // The routine processOneGlyph passed in by the client has the following signature:
    // void f(const SkGlyph& glyph, SkPoint position, SkPoint rounding);
    //
    // * Sub-pixel positioning (2) - use sub-pixel positioning.
    // * Text alignment (3) - text alignment with respect to the glyph's width.
    // * Matrix type (3) - special cases for translation and X-coordinate scaling.
    // * Components per position (2) - the positions vector can have a common Y with different
    //   Xs, or XY-pairs.
    // * Axis Alignment (for sub-pixel positioning) (3) - when using sub-pixel positioning, round
    //   to a whole coordinate instead of using sub-pixel positioning.
    // The number of variations is 108 for sub-pixel and 36 for full-pixel.
    // This routine handles all of them using inline polymorphic variable (no heap allocation).
    template<typename ProcessOneGlyph>
    static void ProcessPosText(
        SkPaint::TextEncoding, const char text[], size_t byteLength,
        SkPoint offset, const SkMatrix& matrix, const SkScalar pos[], int scalarsPerPosition,
        SkPaint::Align textAlignment,
        SkGlyphCache* cache, ProcessOneGlyph&& processOneGlyph);

private:
    // GlyphFinderInterface is the polymorphic base for classes that parse a stream of chars into
    // the right UniChar (or GlyphID) and lookup up the glyph on the cache. The concrete
    // implementations are: Utf8GlyphFinder, Utf16GlyphFinder, Utf32GlyphFinder,
    // and GlyphIdGlyphFinder.
    class GlyphFinderInterface {
    public:
        virtual ~GlyphFinderInterface() {}
        virtual const SkGlyph& lookupGlyph(const char** text) = 0;
        virtual const SkGlyph& lookupGlyphXY(const char** text, SkFixed x, SkFixed y) = 0;
    };

    class UtfNGlyphFinder : public GlyphFinderInterface {
    public:
        explicit UtfNGlyphFinder(SkGlyphCache* cache)
            : fCache(cache) {
            SkASSERT(cache != nullptr);
        }

        const SkGlyph& lookupGlyph(const char** text) override {
            SkASSERT(text != nullptr);
            return fCache->getUnicharMetrics(nextUnichar(text));
        }
        const SkGlyph& lookupGlyphXY(const char** text, SkFixed x, SkFixed y) override {
            SkASSERT(text != nullptr);
            return fCache->getUnicharMetrics(nextUnichar(text), x, y);
        }

    private:
        virtual SkUnichar nextUnichar(const char** text) = 0;
        SkGlyphCache* fCache;
    };

    class Utf8GlyphFinder final : public UtfNGlyphFinder {
    public:
        explicit Utf8GlyphFinder(SkGlyphCache* cache) : UtfNGlyphFinder(cache) { }

    private:
        SkUnichar nextUnichar(const char** text) override { return SkUTF8_NextUnichar(text); }
    };

    class Utf16GlyphFinder final : public UtfNGlyphFinder {
    public:
        explicit Utf16GlyphFinder(SkGlyphCache* cache) : UtfNGlyphFinder(cache) { }

    private:
        SkUnichar nextUnichar(const char** text) override {
            return SkUTF16_NextUnichar((const uint16_t**)text);
        }
    };

    class Utf32GlyphFinder final : public UtfNGlyphFinder {
    public:
        explicit Utf32GlyphFinder(SkGlyphCache* cache) : UtfNGlyphFinder(cache) { }

    private:
        SkUnichar nextUnichar(const char** text) override {
            const int32_t* ptr = *(const int32_t**)text;
            SkUnichar uni = *ptr++;
            *text = (const char*)ptr;
            return uni;
        }
    };

    class GlyphIdGlyphFinder final : public GlyphFinderInterface {
    public:
        explicit GlyphIdGlyphFinder(SkGlyphCache* cache)
            : fCache(cache) {
            SkASSERT(cache != nullptr);
        }

        const SkGlyph& lookupGlyph(const char** text) override {
            return fCache->getGlyphIDMetrics(nextGlyphId(text));
        }
        const SkGlyph& lookupGlyphXY(const char** text, SkFixed x, SkFixed y) override {
            return fCache->getGlyphIDMetrics(nextGlyphId(text), x, y);
        }

    private:
        uint16_t nextGlyphId(const char** text) {
            SkASSERT(text != nullptr);

            const uint16_t* ptr = *(const uint16_t**)text;
            uint16_t glyphID = *ptr;
            ptr += 1;
            *text = (const char*)ptr;
            return glyphID;
        }
        SkGlyphCache* fCache;
    };

    static GlyphFinderInterface* getGlyphFinder(
        SkArenaAlloc* arena, SkPaint::TextEncoding encoding, SkGlyphCache* cache) {
        switch(encoding) {
            case SkPaint::kUTF8_TextEncoding:
                return arena->make<Utf8GlyphFinder>(cache);
            case SkPaint::kUTF16_TextEncoding:
                return arena->make<Utf16GlyphFinder>(cache);
            case SkPaint::kUTF32_TextEncoding:
                return arena->make<Utf32GlyphFinder>(cache);
            case SkPaint::kGlyphID_TextEncoding:
                return arena->make<GlyphIdGlyphFinder>(cache);
        }
        SK_ABORT("Should not get here.");
        return nullptr;
    }

    // PositionReaderInterface reads a point from the pos vector.
    // * HorizontalPositions - assumes a common Y for many X values.
    // * ArbitraryPositions - a list of (X,Y) pairs.
    class PositionReaderInterface {
    public:
        virtual ~PositionReaderInterface() { }
        virtual SkPoint nextPoint() = 0;
    };

    class HorizontalPositions final : public PositionReaderInterface {
    public:
        explicit HorizontalPositions(const SkScalar* positions)
            : fPositions(positions) { }

        SkPoint nextPoint() override {
            SkScalar x = *fPositions++;
            return {x, 0};
        }

    private:
        const SkScalar* fPositions;
    };

    class ArbitraryPositions final : public PositionReaderInterface {
    public:
        explicit ArbitraryPositions(const SkScalar* positions)
            : fPositions(positions) { }

        SkPoint nextPoint() override {
            SkPoint to_return{fPositions[0], fPositions[1]};
            fPositions += 2;
            return to_return;
        }

    private:
        const SkScalar* fPositions;
    };

    // MapperInterface given a point map it through the matrix. There are several shortcut
    // variants.
    // * TranslationMapper - assumes a translation only matrix.
    // * XScaleMapper - assumes an X scaling and a translation.
    // * GeneralMapper - Does all other matricies.
    class MapperInterface {
    public:
        virtual ~MapperInterface() { }

        virtual SkPoint map(SkPoint position) const = 0;
    };

    class TranslationMapper final : public MapperInterface {
    public:
        TranslationMapper(const SkMatrix& matrix, const SkPoint origin)
            : fTranslate(matrix.mapXY(origin.fX, origin.fY)) { }

        SkPoint map(SkPoint position) const override {
            return position + fTranslate;
        }

    private:
        const SkPoint fTranslate;
    };

    class XScaleMapper final : public MapperInterface {
    public:
        XScaleMapper(const SkMatrix& matrix, const SkPoint origin)
            : fTranslate(matrix.mapXY(origin.fX, origin.fY)), fXScale(matrix.getScaleX()) { }

        SkPoint map(SkPoint position) const override {
            return {fXScale * position.fX + fTranslate.fX, fTranslate.fY};
        }

    private:
        const SkPoint fTranslate;
        const SkScalar fXScale;
    };

    // The caller must keep matrix alive while this class is used.
    class GeneralMapper final : public MapperInterface {
    public:
        GeneralMapper(const SkMatrix& matrix, const SkPoint origin)
            : fOrigin(origin), fMatrix(matrix), fMapProc(SkMatrixPriv::GetMapXYProc(matrix)) { }

        SkPoint map(SkPoint position) const override {
            SkPoint result;
            fMapProc(fMatrix, position.fX + fOrigin.fX, position.fY + fOrigin.fY, &result);
            return result;
        }

    private:
        const SkPoint fOrigin;
        const SkMatrix& fMatrix;
        const SkMatrixPriv::MapXYProc fMapProc;
    };

    // TextAlignmentAdjustment handles shifting the glyph based on its width.
    static SkPoint TextAlignmentAdjustment(SkPaint::Align textAlignment, const SkGlyph& glyph) {
        switch (textAlignment) {
            case SkPaint::kLeft_Align:
                return {0.0f, 0.0f};
            case SkPaint::kCenter_Align:
                return {SkFloatToScalar(glyph.fAdvanceX) / 2,
                        SkFloatToScalar(glyph.fAdvanceY) / 2};
            case SkPaint::kRight_Align:
                return {SkFloatToScalar(glyph.fAdvanceX),
                        SkFloatToScalar(glyph.fAdvanceY)};
        }
        // Even though the entire enum is covered above, MVSC doesn't think so. Make it happy.
        SK_ABORT("Should never get here.");
        return {0.0f, 0.0f};
    }

    // The "call" to SkFixedToScalar is actually a macro. It's macros all the way down.
    // Needs to be a macro because you can't have a const float unless you make it constexpr.
    #define kSubpixelRounding (SkFixedToScalar(SkGlyph::kSubpixelRound))

    // The SubpixelPositionRounding function returns a point suitable for rounding a sub-pixel
    // positioned glyph.
    static SkPoint SubpixelPositionRounding(SkAxisAlignment axisAlignment) {
        switch (axisAlignment) {
            case kX_SkAxisAlignment:
                return {kSubpixelRounding, SK_ScalarHalf};
            case kY_SkAxisAlignment:
                return {SK_ScalarHalf, kSubpixelRounding};
            case kNone_SkAxisAlignment:
                return {kSubpixelRounding, kSubpixelRounding};
        }
        SK_ABORT("Should not get here.");
        return {0.0f, 0.0f};
    }

    // The SubpixelAlignment function produces a suitable position for the glyph cache to
    // produce the correct sub-pixel alignment. If a position is aligned with an axis a shortcut
    // of 0 is used for the sub-pixel position.
    static SkIPoint SubpixelAlignment(SkAxisAlignment axisAlignment, SkPoint position) {
        // Only the fractional part of position.fX and position.fY matter, because the result of
        // this function will just be passed to FixedToSub.
        switch (axisAlignment) {
            case kX_SkAxisAlignment:
                return {SkScalarToFixed(SkScalarFraction(position.fX) + kSubpixelRounding), 0};
            case kY_SkAxisAlignment:
                return {0, SkScalarToFixed(SkScalarFraction(position.fY) + kSubpixelRounding)};
            case kNone_SkAxisAlignment:
                return {SkScalarToFixed(SkScalarFraction(position.fX) + kSubpixelRounding),
                        SkScalarToFixed(SkScalarFraction(position.fY) + kSubpixelRounding)};
        }
        SK_ABORT("Should not get here.");
        return {0, 0};
    }

    #undef kSubpixelRounding

    // GlyphFindAndPlaceInterface given the text and position finds the correct glyph and does
    // glyph specific position adjustment. The findAndPositionGlyph method takes text and
    // position and calls processOneGlyph with the correct glyph, final position and rounding
    // terms. The final position is not rounded yet and is the responsibility of processOneGlyph.
    template<typename ProcessOneGlyph>
    class GlyphFindAndPlaceInterface : SkNoncopyable {
    public:
        virtual ~GlyphFindAndPlaceInterface() { }

        // findAndPositionGlyph calculates the position of the glyph, finds the glyph, and
        // returns the position of where the next glyph will be using the glyph's advance and
        // possibly kerning. The returned position is used by drawText, but ignored by drawPosText.
        // The compiler should prune all this calculation if the return value is not used.
        //
        // This should be a pure virtual, but some versions of GCC <= 4.8 have a bug that causes a
        // compile error.
        // See GCC bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60277
        virtual SkPoint findAndPositionGlyph(
            const char** text, SkPoint position, ProcessOneGlyph&& processOneGlyph) {
            SK_ABORT("Should never get here.");
            return {0.0f, 0.0f};
        }
    };

    // GlyphFindAndPlaceSubpixel handles finding and placing glyphs when sub-pixel positioning is
    // requested. After it has found and placed the glyph it calls the templated function
    // ProcessOneGlyph in order to actually perform an action.
    template<typename ProcessOneGlyph, SkPaint::Align kTextAlignment,
             SkAxisAlignment kAxisAlignment>
    class GlyphFindAndPlaceSubpixel final : public GlyphFindAndPlaceInterface<ProcessOneGlyph> {
    public:
        explicit GlyphFindAndPlaceSubpixel(GlyphFinderInterface* glyphFinder)
            : fGlyphFinder(glyphFinder) { }

        SkPoint findAndPositionGlyph(
            const char** text, SkPoint position, ProcessOneGlyph&& processOneGlyph) override {

            if (kTextAlignment != SkPaint::kLeft_Align) {
                // Get the width of an un-sub-pixel positioned glyph for calculating the
                // alignment. This is not needed for kLeftAlign because its adjustment is
                // always {0, 0}.
                const char* tempText = *text;
                const SkGlyph &metricGlyph = fGlyphFinder->lookupGlyph(&tempText);

                if (metricGlyph.fWidth <= 0) {
                    // Exiting early, be sure to update text pointer.
                    *text = tempText;
                    return position + SkPoint{SkFloatToScalar(metricGlyph.fAdvanceX),
                                              SkFloatToScalar(metricGlyph.fAdvanceY)};
                }

                // Adjust the final position by the alignment adjustment.
                position -= TextAlignmentAdjustment(kTextAlignment, metricGlyph);
            }

            // Find the glyph.
            SkIPoint lookupPosition = SkScalarsAreFinite(position.fX, position.fY)
                                      ? SubpixelAlignment(kAxisAlignment, position)
                                      : SkIPoint{0, 0};
            const SkGlyph& renderGlyph =
                fGlyphFinder->lookupGlyphXY(text, lookupPosition.fX, lookupPosition.fY);

            // If the glyph has no width (no pixels) then don't bother processing it.
            if (renderGlyph.fWidth > 0) {
                processOneGlyph(renderGlyph, position,
                                SubpixelPositionRounding(kAxisAlignment));
            }
            return position + SkPoint{SkFloatToScalar(renderGlyph.fAdvanceX),
                                      SkFloatToScalar(renderGlyph.fAdvanceY)};
        }

    private:
        GlyphFinderInterface* fGlyphFinder;
    };

    enum SelectKerning {
        kNoKerning = false,
        kUseKerning = true
    };

    // GlyphFindAndPlaceFullPixel handles finding and placing glyphs when no sub-pixel
    // positioning is requested. The kUseKerning argument should be true for drawText, and false
    // for drawPosText.
    template<typename ProcessOneGlyph, SkPaint::Align kTextAlignment, SelectKerning kUseKerning>
    class GlyphFindAndPlaceFullPixel final : public GlyphFindAndPlaceInterface<ProcessOneGlyph> {
    public:
        explicit GlyphFindAndPlaceFullPixel(GlyphFinderInterface* glyphFinder)
            : fGlyphFinder(glyphFinder) {
            // Kerning can only be used with SkPaint::kLeft_Align
            static_assert(!kUseKerning || SkPaint::kLeft_Align == kTextAlignment,
                          "Kerning can only be used with left aligned text.");
        }

        SkPoint findAndPositionGlyph(
            const char** text, SkPoint position, ProcessOneGlyph&& processOneGlyph) override {
            SkPoint finalPosition = position;
            const SkGlyph& glyph = fGlyphFinder->lookupGlyph(text);
            if (kUseKerning) {
                finalPosition += {fAutoKern.adjust(glyph), 0.0f};
            }
            if (glyph.fWidth > 0) {
                finalPosition -= TextAlignmentAdjustment(kTextAlignment, glyph);
                processOneGlyph(glyph, finalPosition, {SK_ScalarHalf, SK_ScalarHalf});
            }
            return finalPosition + SkPoint{SkFloatToScalar(glyph.fAdvanceX),
                                           SkFloatToScalar(glyph.fAdvanceY)};
        }

    private:
        GlyphFinderInterface* fGlyphFinder;

        SkAutoKern fAutoKern;
    };

    template <typename ProcessOneGlyph, SkPaint::Align kTextAlignment>
    static GlyphFindAndPlaceInterface<ProcessOneGlyph>* getSubpixel(
        SkArenaAlloc* arena, SkAxisAlignment axisAlignment, GlyphFinderInterface* glyphFinder)
    {
        switch (axisAlignment) {
            case kX_SkAxisAlignment:
                return arena->make<GlyphFindAndPlaceSubpixel<
                    ProcessOneGlyph, kTextAlignment, kX_SkAxisAlignment>>(glyphFinder);
            case kNone_SkAxisAlignment:
                return arena->make<GlyphFindAndPlaceSubpixel<
                    ProcessOneGlyph, kTextAlignment, kNone_SkAxisAlignment>>(glyphFinder);
            case kY_SkAxisAlignment:
                return arena->make<GlyphFindAndPlaceSubpixel<
                    ProcessOneGlyph, kTextAlignment, kY_SkAxisAlignment>>(glyphFinder);
        }
        SK_ABORT("Should never get here.");
        return nullptr;
    }

    static SkPoint MeasureText(
        GlyphFinderInterface* glyphFinder, const char text[], size_t byteLength) {
        SkScalar    x = 0, y = 0;
        const char* stop = text + byteLength;

        SkAutoKern  autokern;

        while (text < stop) {
            // don't need x, y here, since all subpixel variants will have the
            // same advance
            const SkGlyph& glyph = glyphFinder->lookupGlyph(&text);

            x += autokern.adjust(glyph) + SkFloatToScalar(glyph.fAdvanceX);
            y += SkFloatToScalar(glyph.fAdvanceY);
        }
        SkASSERT(text == stop);
        return {x, y};
    }
};

template<typename ProcessOneGlyph>
inline void SkFindAndPlaceGlyph::ProcessPosText(
    SkPaint::TextEncoding textEncoding, const char text[], size_t byteLength,
    SkPoint offset, const SkMatrix& matrix, const SkScalar pos[], int scalarsPerPosition,
    SkPaint::Align textAlignment,
    SkGlyphCache* cache, ProcessOneGlyph&& processOneGlyph) {

    SkAxisAlignment axisAlignment = cache->getScalerContext()->computeAxisAlignmentForHText();
    uint32_t mtype = matrix.getType();

    // Specialized code for handling the most common case for blink.
    if (textEncoding == SkPaint::kGlyphID_TextEncoding
        && textAlignment == SkPaint::kLeft_Align
        && axisAlignment == kX_SkAxisAlignment
        && cache->isSubpixel()
        && mtype <= SkMatrix::kTranslate_Mask)
    {
        GlyphIdGlyphFinder glyphFinder(cache);
        using Positioner =
            GlyphFindAndPlaceSubpixel <
                ProcessOneGlyph, SkPaint::kLeft_Align, kX_SkAxisAlignment>;
        HorizontalPositions hPositions{pos};
        ArbitraryPositions  aPositions{pos};
        PositionReaderInterface* positions = nullptr;
        if (scalarsPerPosition == 2) {
            positions = &aPositions;
        } else {
            positions = &hPositions;
        }
        TranslationMapper mapper{matrix, offset};
        Positioner positioner(&glyphFinder);
        const char* cursor = text;
        const char* stop = text + byteLength;
        while (cursor < stop) {
            SkPoint mappedPoint = mapper.TranslationMapper::map(positions->nextPoint());
            positioner.Positioner::findAndPositionGlyph(
                &cursor, mappedPoint, std::forward<ProcessOneGlyph>(processOneGlyph));
        }
        return;
    }

    SkSTArenaAlloc<120> arena;

    GlyphFinderInterface* glyphFinder = getGlyphFinder(&arena, textEncoding, cache);

    PositionReaderInterface* positionReader = nullptr;
    if (2 == scalarsPerPosition) {
        positionReader = arena.make<ArbitraryPositions>(pos);
    } else {
        positionReader = arena.make<HorizontalPositions>(pos);
    }

    MapperInterface* mapper = nullptr;
    if (mtype & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)
        || scalarsPerPosition == 2) {
        mapper = arena.make<GeneralMapper>(matrix, offset);
    } else if (mtype & SkMatrix::kScale_Mask) {
        mapper = arena.make<XScaleMapper>(matrix, offset);
    } else {
        mapper = arena.make<TranslationMapper>(matrix, offset);
    }

    GlyphFindAndPlaceInterface<ProcessOneGlyph>* findAndPosition = nullptr;
    if (cache->isSubpixel()) {
        switch (textAlignment) {
            case SkPaint::kLeft_Align:
                findAndPosition = getSubpixel<ProcessOneGlyph, SkPaint::kLeft_Align>(
                    &arena, axisAlignment, glyphFinder);
                break;
            case SkPaint::kCenter_Align:
                findAndPosition = getSubpixel<ProcessOneGlyph, SkPaint::kCenter_Align>(
                    &arena, axisAlignment, glyphFinder);
                break;
            case SkPaint::kRight_Align:
                findAndPosition = getSubpixel<ProcessOneGlyph, SkPaint::kRight_Align>(
                    &arena, axisAlignment, glyphFinder);
                break;
        }
    } else {
        switch (textAlignment) {
            case SkPaint::kLeft_Align:
                findAndPosition = arena.make<
                    GlyphFindAndPlaceFullPixel<ProcessOneGlyph,
                        SkPaint::kLeft_Align, kNoKerning>>(glyphFinder);
                break;
            case SkPaint::kCenter_Align:
                findAndPosition = arena.make<
                    GlyphFindAndPlaceFullPixel<ProcessOneGlyph,
                        SkPaint::kCenter_Align, kNoKerning>>(glyphFinder);
                break;
            case SkPaint::kRight_Align:
                findAndPosition = arena.make<
                    GlyphFindAndPlaceFullPixel<ProcessOneGlyph,
                        SkPaint::kRight_Align, kNoKerning>>(glyphFinder);
                break;
        }
    }

    const char* stop = text + byteLength;
    while (text < stop) {
        SkPoint mappedPoint = mapper->map(positionReader->nextPoint());
        findAndPosition->findAndPositionGlyph(
            &text, mappedPoint, std::forward<ProcessOneGlyph>(processOneGlyph));
    }
}

template<typename ProcessOneGlyph>
inline void SkFindAndPlaceGlyph::ProcessText(
    SkPaint::TextEncoding textEncoding, const char text[], size_t byteLength,
    SkPoint offset, const SkMatrix& matrix, SkPaint::Align textAlignment,
    SkGlyphCache* cache, ProcessOneGlyph&& processOneGlyph) {
    SkSTArenaAlloc<64> arena;

    // transform the starting point
    matrix.mapPoints(&offset, 1);

    GlyphFinderInterface* glyphFinder = getGlyphFinder(&arena, textEncoding, cache);

    // need to measure first
    if (textAlignment != SkPaint::kLeft_Align) {
        SkVector stop = MeasureText(glyphFinder, text, byteLength);

        if (textAlignment == SkPaint::kCenter_Align) {
            stop *= SK_ScalarHalf;
        }
        offset -= stop;
    }

    GlyphFindAndPlaceInterface<ProcessOneGlyph>* findAndPosition = nullptr;
    if (cache->isSubpixel()) {
        SkAxisAlignment axisAlignment = cache->getScalerContext()->computeAxisAlignmentForHText();
        findAndPosition = getSubpixel<ProcessOneGlyph, SkPaint::kLeft_Align>(
            &arena, axisAlignment, glyphFinder);
    } else {
        using FullPixel =
            GlyphFindAndPlaceFullPixel<ProcessOneGlyph, SkPaint::kLeft_Align, kUseKerning>;
        findAndPosition = arena.make<FullPixel>(glyphFinder);
    }

    const char* stop = text + byteLength;
    SkPoint current = offset;
    while (text < stop) {
        current =
            findAndPosition->findAndPositionGlyph(
                &text, current, std::forward<ProcessOneGlyph>(processOneGlyph));

    }
}

#endif  // SkFindAndPositionGlyph_DEFINED
