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

#ifndef SkTextBlobPriv_DEFINED
#define SkTextBlobPriv_DEFINED

#include "include/core/SkColorFilter.h"
#include "include/core/SkFont.h"
#include "include/core/SkImageFilter.h"
#include "include/core/SkMaskFilter.h"
#include "include/core/SkPathEffect.h"
#include "include/core/SkShader.h"
#include "include/core/SkTextBlob.h"
#include "include/core/SkTypeface.h"
#include "src/core/SkPaintPriv.h"
#include "src/core/SkSafeMath.h"

class SkReadBuffer;
class SkWriteBuffer;

class SkTextBlobPriv {
public:
    /**
     *  Serialize to a buffer.
     */
    static void Flatten(const SkTextBlob& , SkWriteBuffer&);

    /**
     *  Recreate an SkTextBlob that was serialized into a buffer.
     *
     *  @param  SkReadBuffer Serialized blob data.
     *  @return A new SkTextBlob representing the serialized data, or NULL if the buffer is
     *          invalid.
     */
    static sk_sp<SkTextBlob> MakeFromBuffer(SkReadBuffer&);

    static bool HasRSXForm(const SkTextBlob& blob);
};

//
// Textblob data is laid out into externally-managed storage as follows:
//
//    -----------------------------------------------------------------------------
//   | SkTextBlob | RunRecord | Glyphs[] | Pos[] | RunRecord | Glyphs[] | Pos[] | ...
//    -----------------------------------------------------------------------------
//
//  Each run record describes a text blob run, and can be used to determine the (implicit)
//  location of the following record.
//
// Extended Textblob runs have more data after the Pos[] array:
//
//    -------------------------------------------------------------------------
//    ... | RunRecord | Glyphs[] | Pos[] | TextSize | Clusters[] | Text[] | ...
//    -------------------------------------------------------------------------
//
// To determine the length of the extended run data, the TextSize must be read.
//
// Extended Textblob runs may be mixed with non-extended runs.

SkDEBUGCODE(static const unsigned kRunRecordMagic = 0xb10bcafe;)

class SkTextBlob::RunRecord {
public:
    RunRecord(uint32_t count, uint32_t textSize,  const SkPoint& offset, const SkFont& font, GlyphPositioning pos)
            : fFont(font)
            , fCount(count)
            , fOffset(offset)
            , fFlags(pos) {
        SkASSERT(static_cast<unsigned>(pos) <= Flags::kPositioning_Mask);

        SkDEBUGCODE(fMagic = kRunRecordMagic);
        if (textSize > 0) {
            fFlags |= kExtended_Flag;
            *this->textSizePtr() = textSize;
        }
    }

    uint32_t glyphCount() const {
        return fCount;
    }

    const SkPoint& offset() const {
        return fOffset;
    }

    const SkFont& font() const {
        return fFont;
    }

    GlyphPositioning positioning() const {
        return static_cast<GlyphPositioning>(fFlags & kPositioning_Mask);
    }

    uint16_t* glyphBuffer() const {
        static_assert(SkIsAlignPtr(sizeof(RunRecord)), "");
        // Glyphs are stored immediately following the record.
        return reinterpret_cast<uint16_t*>(const_cast<RunRecord*>(this) + 1);
    }

    // can be aliased with pointBuffer() or xformBuffer()
    SkScalar* posBuffer() const {
        // Position scalars follow the (aligned) glyph buffer.
        return reinterpret_cast<SkScalar*>(reinterpret_cast<uint8_t*>(this->glyphBuffer()) +
                                           SkAlign4(fCount * sizeof(uint16_t)));
    }

    // alias for posBuffer()
    SkPoint* pointBuffer() const {
        SkASSERT(this->positioning() == (GlyphPositioning)2);
        return reinterpret_cast<SkPoint*>(this->posBuffer());
    }

    // alias for posBuffer()
    SkRSXform* xformBuffer() const {
        SkASSERT(this->positioning() == (GlyphPositioning)3);
        return reinterpret_cast<SkRSXform*>(this->posBuffer());
    }

    uint32_t textSize() const { return isExtended() ? *this->textSizePtr() : 0; }

    uint32_t* clusterBuffer() const {
        // clusters follow the textSize.
        return isExtended() ? 1 + this->textSizePtr() : nullptr;
    }

    char* textBuffer() const {
        return isExtended()
               ? reinterpret_cast<char*>(this->clusterBuffer() + fCount)
               : nullptr;
    }

    bool isLastRun() const { return SkToBool(fFlags & kLast_Flag); }

    static size_t StorageSize(uint32_t glyphCount, uint32_t textSize,
                              SkTextBlob::GlyphPositioning positioning,
                              SkSafeMath* safe);

    static const RunRecord* First(const SkTextBlob* blob);

    static const RunRecord* Next(const RunRecord* run);

    void validate(const uint8_t* storageTop) const;

private:
    friend class SkTextBlobBuilder;

    enum Flags {
        kPositioning_Mask = 0x03, // bits 0-1 reserved for positioning
        kLast_Flag        = 0x04, // set for the last blob run
        kExtended_Flag    = 0x08, // set for runs with text/cluster info
    };

    static const RunRecord* NextUnchecked(const RunRecord* run);

    static size_t PosCount(uint32_t glyphCount,
                           SkTextBlob::GlyphPositioning positioning,
                           SkSafeMath* safe);

    uint32_t* textSizePtr() const;

    void grow(uint32_t count);

    bool isExtended() const {
        return fFlags & kExtended_Flag;
    }

    SkFont           fFont;
    uint32_t         fCount;
    SkPoint          fOffset;
    uint32_t         fFlags;

    SkDEBUGCODE(unsigned fMagic;)
};

/**
 *  Iterate through all of the text runs of the text blob.  For example:
 *    for (SkTextBlobRunIterator it(blob); !it.done(); it.next()) {
 *         .....
 *    }
 */
class SkTextBlobRunIterator {
public:
    SkTextBlobRunIterator(const SkTextBlob* blob);

    enum GlyphPositioning : uint8_t {
        kDefault_Positioning      = 0, // Default glyph advances -- zero scalars per glyph.
        kHorizontal_Positioning   = 1, // Horizontal positioning -- one scalar per glyph.
        kFull_Positioning         = 2, // Point positioning -- two scalars per glyph.
        kRSXform_Positioning      = 3, // RSXform positioning -- four scalars per glyph.
    };

    bool done() const {
        return !fCurrentRun;
    }
    void next();

    uint32_t glyphCount() const {
        SkASSERT(!this->done());
        return fCurrentRun->glyphCount();
    }
    const uint16_t* glyphs() const {
        SkASSERT(!this->done());
        return fCurrentRun->glyphBuffer();
    }
    const SkScalar* pos() const {
        SkASSERT(!this->done());
        return fCurrentRun->posBuffer();
    }
    // alias for pos()
    const SkPoint* points() const {
        return fCurrentRun->pointBuffer();
    }
    // alias for pos()
    const SkRSXform* xforms() const {
        return fCurrentRun->xformBuffer();
    }
    const SkPoint& offset() const {
        SkASSERT(!this->done());
        return fCurrentRun->offset();
    }
    const SkFont& font() const {
        SkASSERT(!this->done());
        return fCurrentRun->font();
    }
    GlyphPositioning positioning() const;
    unsigned scalarsPerGlyph() const;
    uint32_t* clusters() const {
        SkASSERT(!this->done());
        return fCurrentRun->clusterBuffer();
    }
    uint32_t textSize() const {
        SkASSERT(!this->done());
        return fCurrentRun->textSize();
    }
    char* text() const {
        SkASSERT(!this->done());
        return fCurrentRun->textBuffer();
    }

    bool isLCD() const;

private:
    const SkTextBlob::RunRecord* fCurrentRun;

    SkDEBUGCODE(uint8_t* fStorageTop;)
};

inline bool SkTextBlobPriv::HasRSXForm(const SkTextBlob& blob) {
    for (SkTextBlobRunIterator i{&blob}; !i.done(); i.next()) {
        if (i.positioning() == SkTextBlobRunIterator::kRSXform_Positioning) {
            return true;
        }
    }
    return false;
}

#endif // SkTextBlobPriv_DEFINED
