/*
 * Copyright 2018 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef SkGlyphRun_DEFINED
#define SkGlyphRun_DEFINED

#include <functional>
#include <optional>
#include <vector>

#include "include/core/SkFont.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRSXform.h"
#include "include/core/SkSpan.h"
#include "include/core/SkTypes.h"
#include "include/private/base/SkTemplates.h"
#include "src/base/SkZip.h"

class SkBaseDevice;
class SkCanvas;
class SkGlyph;
class SkTextBlob;
class SkTextBlobRunIterator;

namespace sktext {
class GlyphRunBuilder;
class GlyphRunList;

class GlyphRun {
public:
    GlyphRun(const SkFont& font,
             SkSpan<const SkPoint> positions,
             SkSpan<const SkGlyphID> glyphIDs,
             SkSpan<const char> text,
             SkSpan<const uint32_t> clusters,
             SkSpan<const SkVector> scaledRotations);

    GlyphRun(const GlyphRun& glyphRun, const SkFont& font);

    size_t runSize() const { return fSource.size(); }
    SkSpan<const SkPoint> positions() const { return fSource.get<1>(); }
    SkSpan<const SkGlyphID> glyphsIDs() const { return fSource.get<0>(); }
    SkZip<const SkGlyphID, const SkPoint> source() const { return fSource; }
    const SkFont& font() const { return fFont; }
    SkSpan<const uint32_t> clusters() const { return fClusters; }
    SkSpan<const char> text() const { return fText; }
    SkSpan<const SkVector> scaledRotations() const { return fScaledRotations; }

private:
    // GlyphIDs and positions.
    const SkZip<const SkGlyphID, const SkPoint> fSource;
    // Original text from SkTextBlob if present. Will be empty of not present.
    const SkSpan<const char> fText;
    // Original clusters from SkTextBlob if present. Will be empty if not present.
    const SkSpan<const uint32_t>   fClusters;
    // Possible RSXForm information
    const SkSpan<const SkVector> fScaledRotations;
    // Font for this run modified to have glyph encoding and left alignment.
    SkFont fFont;
};

class GlyphRunList {
    SkSpan<const GlyphRun> fGlyphRuns;

public:
    // Blob maybe null.
    GlyphRunList(const SkTextBlob* blob,
                 SkRect bounds,
                 SkPoint origin,
                 SkSpan<const GlyphRun> glyphRunList,
                 GlyphRunBuilder* builder);

    GlyphRunList(const GlyphRun& glyphRun,
                 const SkRect& bounds,
                 SkPoint origin,
                 GlyphRunBuilder* builder);
    uint64_t uniqueID() const;
    bool anyRunsLCD() const;
    void temporaryShuntBlobNotifyAddedToCache(uint32_t cacheID) const;

    bool canCache() const { return fOriginalTextBlob != nullptr; }
    size_t runCount() const { return fGlyphRuns.size(); }
    size_t totalGlyphCount() const {
        size_t glyphCount = 0;
        for (const GlyphRun& run : *this) {
            glyphCount += run.runSize();
        }
        return glyphCount;
    }
    size_t maxGlyphRunSize() const {
        size_t size = 0;
        for (const GlyphRun& run : *this) {
            size = std::max(run.runSize(), size);
        }
        return size;
    }

    bool hasRSXForm() const {
        for (const GlyphRun& run : *this) {
            if (!run.scaledRotations().empty()) { return true; }
        }
        return false;
    }

    sk_sp<SkTextBlob> makeBlob() const;

    SkPoint origin() const { return fOrigin; }
    SkRect sourceBounds() const { return fSourceBounds; }
    SkRect sourceBoundsWithOrigin() const { return fSourceBounds.makeOffset(fOrigin); }
    const SkTextBlob* blob() const { return fOriginalTextBlob; }
    GlyphRunBuilder* builder() const { return fBuilder; }

    auto begin() -> decltype(fGlyphRuns.begin())               { return fGlyphRuns.begin();      }
    auto end()   -> decltype(fGlyphRuns.end())                 { return fGlyphRuns.end();        }
    auto begin() const -> decltype(std::cbegin(fGlyphRuns))    { return std::cbegin(fGlyphRuns); }
    auto end()   const -> decltype(std::cend(fGlyphRuns))      { return std::cend(fGlyphRuns);   }
    auto size()  const -> decltype(fGlyphRuns.size())          { return fGlyphRuns.size();       }
    auto empty() const -> decltype(fGlyphRuns.empty())         { return fGlyphRuns.empty();      }
    auto operator [] (size_t i) const -> decltype(fGlyphRuns[i]) { return fGlyphRuns[i];         }

private:
    // The text blob is needed to hook up the call back that the SkTextBlob destructor calls. It
    // should be used for nothing else.
    const SkTextBlob* fOriginalTextBlob{nullptr};
    const SkRect fSourceBounds{SkRect::MakeEmpty()};
    const SkPoint fOrigin = {0, 0};
    GlyphRunBuilder* const fBuilder;
};

class GlyphRunBuilder {
public:
    GlyphRunList makeGlyphRunList(const GlyphRun& run, const SkPaint& paint, SkPoint origin);
    const GlyphRunList& textToGlyphRunList(const SkFont& font,
                                           const SkPaint& paint,
                                           const void* bytes,
                                           size_t byteLength,
                                           SkPoint origin,
                                           SkTextEncoding encoding = SkTextEncoding::kUTF8);
    const GlyphRunList& blobToGlyphRunList(const SkTextBlob& blob, SkPoint origin);
    std::tuple<SkSpan<const SkPoint>, SkSpan<const SkVector>>
            convertRSXForm(SkSpan<const SkRSXform> xforms);

    bool empty() const { return fGlyphRunListStorage.empty(); }

private:
    void initialize(const SkTextBlob& blob);
    void prepareBuffers(int positionCount, int RSXFormCount);

    SkSpan<const SkGlyphID> textToGlyphIDs(
            const SkFont& font, const void* bytes, size_t byteLength, SkTextEncoding);

    void makeGlyphRun(
            const SkFont& font,
            SkSpan<const SkGlyphID> glyphIDs,
            SkSpan<const SkPoint> positions,
            SkSpan<const char> text,
            SkSpan<const uint32_t> clusters,
            SkSpan<const SkVector> scaledRotations);

    const GlyphRunList& setGlyphRunList(
            const SkTextBlob* blob, const SkRect& bounds, SkPoint origin);

    int fMaxTotalRunSize{0};
    skia_private::AutoTMalloc<SkPoint> fPositions;
    int fMaxScaledRotations{0};
    skia_private::AutoTMalloc<SkVector> fScaledRotations;

    std::vector<GlyphRun> fGlyphRunListStorage;
    std::optional<GlyphRunList> fGlyphRunList;  // Defaults to no value;

    // Used as a temporary for preparing using utfN text. This implies that only one run of
    // glyph ids will ever be needed because blobs are already glyph based.
    std::vector<SkGlyphID> fScratchGlyphIDs;

};
}  // namespace sktext

#endif  // SkGlyphRun_DEFINED
