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


#include "SkBitmapHeap.h"
#include "SkChecksum.h"
#include "SkChunkAlloc.h"
#include "SkReadBuffer.h"
#include "SkWriteBuffer.h"
#include "SkPaint.h"
#include "SkPicture.h"
#include "SkPtrRecorder.h"
#include "SkTDynamicHash.h"
#include "SkTRefArray.h"

enum DrawType {
    UNUSED,
    CLIP_PATH,
    CLIP_REGION,
    CLIP_RECT,
    CLIP_RRECT,
    CONCAT,
    DRAW_BITMAP,
    DRAW_BITMAP_MATRIX,
    DRAW_BITMAP_NINE,
    DRAW_BITMAP_RECT_TO_RECT,
    DRAW_CLEAR,
    DRAW_DATA,
    DRAW_OVAL,
    DRAW_PAINT,
    DRAW_PATH,
    DRAW_PICTURE,
    DRAW_POINTS,
    DRAW_POS_TEXT,
    DRAW_POS_TEXT_TOP_BOTTOM, // fast variant of DRAW_POS_TEXT
    DRAW_POS_TEXT_H,
    DRAW_POS_TEXT_H_TOP_BOTTOM, // fast variant of DRAW_POS_TEXT_H
    DRAW_RECT,
    DRAW_RRECT,
    DRAW_SPRITE,
    DRAW_TEXT,
    DRAW_TEXT_ON_PATH,
    DRAW_TEXT_TOP_BOTTOM,   // fast variant of DRAW_TEXT
    DRAW_VERTICES,
    RESTORE,
    ROTATE,
    SAVE,
    SAVE_LAYER,
    SCALE,
    SET_MATRIX,
    SKEW,
    TRANSLATE,
    NOOP,
    BEGIN_COMMENT_GROUP,
    COMMENT,
    END_COMMENT_GROUP,

    // new ops -- feel free to re-alphabetize on next version bump
    DRAW_DRRECT,
    PUSH_CULL,
    POP_CULL,

    DRAW_PATCH, // could not add in aphabetical order
    DRAW_PICTURE_MATRIX_PAINT,
    DRAW_TEXT_BLOB,

    LAST_DRAWTYPE_ENUM = DRAW_TEXT_BLOB
};

// In the 'match' method, this constant will match any flavor of DRAW_BITMAP*
static const int kDRAW_BITMAP_FLAVOR = LAST_DRAWTYPE_ENUM+1;

enum DrawVertexFlags {
    DRAW_VERTICES_HAS_TEXS    = 0x01,
    DRAW_VERTICES_HAS_COLORS  = 0x02,
    DRAW_VERTICES_HAS_INDICES = 0x04,
    DRAW_VERTICES_HAS_XFER    = 0x08,
};

///////////////////////////////////////////////////////////////////////////////
// clipparams are packed in 5 bits
//  doAA:1 | regionOp:4

static inline uint32_t ClipParams_pack(SkRegion::Op op, bool doAA) {
    unsigned doAABit = doAA ? 1 : 0;
    return (doAABit << 4) | op;
}

static inline SkRegion::Op ClipParams_unpackRegionOp(uint32_t packed) {
    return (SkRegion::Op)(packed & 0xF);
}

static inline bool ClipParams_unpackDoAA(uint32_t packed) {
    return SkToBool((packed >> 4) & 1);
}

///////////////////////////////////////////////////////////////////////////////

class SkTypefacePlayback {
public:
    SkTypefacePlayback();
    virtual ~SkTypefacePlayback();

    int count() const { return fCount; }

    void reset(const SkRefCntSet*);

    void setCount(int count);
    SkRefCnt* set(int index, SkRefCnt*);

    void setupBuffer(SkReadBuffer& buffer) const {
        buffer.setTypefaceArray((SkTypeface**)fArray, fCount);
    }

protected:
    int fCount;
    SkRefCnt** fArray;
};

class SkFactoryPlayback {
public:
    SkFactoryPlayback(int count) : fCount(count) {
        fArray = SkNEW_ARRAY(SkFlattenable::Factory, count);
    }

    ~SkFactoryPlayback() {
        SkDELETE_ARRAY(fArray);
    }

    SkFlattenable::Factory* base() const { return fArray; }

    void setupBuffer(SkReadBuffer& buffer) const {
        buffer.setFactoryPlayback(fArray, fCount);
    }

private:
    int fCount;
    SkFlattenable::Factory* fArray;
};

///////////////////////////////////////////////////////////////////////////////
//
//
// The following templated classes provide an efficient way to store and compare
// objects that have been flattened (i.e. serialized in an ordered binary
// format).
//
// SkFlatData:       is a simple indexable container for the flattened data
//                   which is agnostic to the type of data is is indexing. It is
//                   also responsible for flattening/unflattening objects but
//                   details of that operation are hidden in the provided traits
// SkFlatDictionary: is an abstract templated dictionary that maintains a
//                   searchable set of SkFlatData objects of type T.
// SkFlatController: is an interface provided to SkFlatDictionary which handles
//                   allocation (and unallocation in some cases). It also holds
//                   ref count recorders and the like.
//
// NOTE: any class that wishes to be used in conjunction with SkFlatDictionary must subclass the
// dictionary and provide the necessary flattening traits.  SkFlatController must also be
// implemented, or SkChunkFlatController can be used to use an SkChunkAllocator and never do
// replacements.
//
//
///////////////////////////////////////////////////////////////////////////////

class SkFlatData;

class SkFlatController : public SkRefCnt {
public:
    SK_DECLARE_INST_COUNT(SkFlatController)

    SkFlatController(uint32_t writeBufferFlags = 0);
    virtual ~SkFlatController();
    /**
     * Return a new block of memory for the SkFlatDictionary to use.
     * This memory is owned by the controller and has the same lifetime unless you
     * call unalloc(), in which case it may be freed early.
     */
    virtual void* allocThrow(size_t bytes) = 0;

    /**
     * Hint that this block, which was allocated with allocThrow, is no longer needed.
     * The implementation may choose to free this memory any time beteween now and destruction.
     */
    virtual void unalloc(void* ptr) = 0;

    /**
     * Used during creation and unflattening of SkFlatData objects. If the
     * objects being flattened contain bitmaps they are stored in this heap
     * and the flattenable stores the index to the bitmap on the heap.
     * This should be set by the protected setBitmapHeap.
     */
    SkBitmapHeap* getBitmapHeap() { return fBitmapHeap; }

    /**
     * Used during creation of SkFlatData objects. If a typeface recorder is
     * required to flatten the objects being flattened (i.e. for SkPaints), this
     * should be set by the protected setTypefaceSet.
     */
    SkRefCntSet* getTypefaceSet() { return fTypefaceSet; }

    /**
     * Used during unflattening of the SkFlatData objects in the
     * SkFlatDictionary. Needs to be set by the protected setTypefacePlayback
     * and needs to be reset to the SkRefCntSet passed to setTypefaceSet.
     */
    SkTypefacePlayback* getTypefacePlayback() { return fTypefacePlayback; }

    /**
     * Optional factory recorder used during creation of SkFlatData objects. Set
     * using the protected method setNamedFactorySet.
     */
    SkNamedFactorySet* getNamedFactorySet() { return fFactorySet; }

    /**
     * Flags to use during creation of SkFlatData objects. Defaults to zero.
     */
    uint32_t getWriteBufferFlags() { return fWriteBufferFlags; }

protected:
    /**
     * Set an SkBitmapHeap to be used to store/read SkBitmaps. Ref counted.
     */
    void setBitmapHeap(SkBitmapHeap*);

    /**
     * Set an SkRefCntSet to be used to store SkTypefaces during flattening. Ref
     * counted.
     */
    void setTypefaceSet(SkRefCntSet*);

    /**
     * Set an SkTypefacePlayback to be used to find references to SkTypefaces
     * during unflattening. Should be reset to the set provided to
     * setTypefaceSet.
     */
    void setTypefacePlayback(SkTypefacePlayback*);

    /**
     * Set an SkNamedFactorySet to be used to store Factorys and their
     * corresponding names during flattening. Ref counted. Returns the same
     * set as a convenience.
     */
    SkNamedFactorySet* setNamedFactorySet(SkNamedFactorySet*);

private:
    SkBitmapHeap*       fBitmapHeap;
    SkRefCntSet*        fTypefaceSet;
    SkTypefacePlayback* fTypefacePlayback;
    SkNamedFactorySet*  fFactorySet;
    const uint32_t      fWriteBufferFlags;

    typedef SkRefCnt INHERITED;
};

class SkFlatData {
public:
    // Flatten obj into an SkFlatData with this index.  controller owns the SkFlatData*.
    template <typename Traits, typename T>
    static SkFlatData* Create(SkFlatController* controller, const T& obj, int index) {
        // A buffer of 256 bytes should fit most paints, regions, and matrices.
        uint32_t storage[64];
        SkWriteBuffer buffer(storage, sizeof(storage), controller->getWriteBufferFlags());

        buffer.setBitmapHeap(controller->getBitmapHeap());
        buffer.setTypefaceRecorder(controller->getTypefaceSet());
        buffer.setNamedFactoryRecorder(controller->getNamedFactorySet());

        Traits::Flatten(buffer, obj);
        size_t size = buffer.bytesWritten();
        SkASSERT(SkIsAlign4(size));

        // Allocate enough memory to hold SkFlatData struct and the flat data itself.
        size_t allocSize = sizeof(SkFlatData) + size;
        SkFlatData* result = (SkFlatData*) controller->allocThrow(allocSize);

        // Put the serialized contents into the data section of the new allocation.
        buffer.writeToMemory(result->data());
        // Stamp the index, size and checksum in the header.
        result->stampHeader(index, SkToS32(size));
        return result;
    }

    // Unflatten this into result, using bitmapHeap and facePlayback for bitmaps and fonts if given
    template <typename Traits, typename T>
    void unflatten(T* result,
                   SkBitmapHeap* bitmapHeap = NULL,
                   SkTypefacePlayback* facePlayback = NULL) const {
        SkReadBuffer buffer(this->data(), fFlatSize);

        if (bitmapHeap) {
            buffer.setBitmapStorage(bitmapHeap);
        }
        if (facePlayback) {
            facePlayback->setupBuffer(buffer);
        }

        Traits::Unflatten(buffer, result);
        SkASSERT(fFlatSize == (int32_t)buffer.offset());
    }

    // Do these contain the same data?  Ignores index() and topBot().
    bool operator==(const SkFlatData& that) const {
        if (this->checksum() != that.checksum() || this->flatSize() != that.flatSize()) {
            return false;
        }
        return memcmp(this->data(), that.data(), this->flatSize()) == 0;
    }

    int index() const { return fIndex; }
    const uint8_t* data() const { return (const uint8_t*)this + sizeof(*this); }
    size_t flatSize() const { return fFlatSize; }
    uint32_t checksum() const { return fChecksum; }

    // Returns true if fTopBot[] has been recorded.
    bool isTopBotWritten() const {
        return !SkScalarIsNaN(fTopBot[0]);
    }

    // Returns fTopBot array, so it can be passed to a routine to compute them.
    // For efficiency, we assert that fTopBot have not been recorded yet.
    SkScalar* writableTopBot() const {
        SkASSERT(!this->isTopBotWritten());
        return fTopBot;
    }

    // Return the topbot[] after it has been recorded.
    const SkScalar* topBot() const {
        SkASSERT(this->isTopBotWritten());
        return fTopBot;
    }

private:
    struct HashTraits {
        static const SkFlatData& GetKey(const SkFlatData& flat) { return flat; }
        static uint32_t Hash(const SkFlatData& flat) { return flat.checksum(); }
    };

    void setIndex(int index) { fIndex = index; }
    uint8_t* data() { return (uint8_t*)this + sizeof(*this); }

    // This assumes the payload flat data has already been written and does not modify it.
    void stampHeader(int index, int32_t size) {
        SkASSERT(SkIsAlign4(size));
        fIndex     = index;
        fFlatSize  = size;
        fTopBot[0] = SK_ScalarNaN;  // Mark as unwritten.
        fChecksum  = SkChecksum::Compute((uint32_t*)this->data(), size);
    }

    int fIndex;
    int32_t fFlatSize;
    uint32_t fChecksum;
    mutable SkScalar fTopBot[2];  // Cache of FontMetrics fTop, fBottom.  Starts as [NaN,?].
    // uint32_t flattenedData[] implicitly hangs off the end.

    template <typename T, typename Traits> friend class SkFlatDictionary;
};

template <typename T, typename Traits>
class SkFlatDictionary {
public:
    explicit SkFlatDictionary(SkFlatController* controller)
    : fController(SkRef(controller))
    , fScratch(controller->getWriteBufferFlags())
    , fReady(false) {
        this->reset();
    }

    /**
     * Clears the dictionary of all entries. However, it does NOT free the
     * memory that was allocated for each entry (that's owned by controller).
     */
    void reset() {
        fIndexedData.rewind();
    }

    int count() const {
        SkASSERT(fHash.count() == fIndexedData.count());
        return fHash.count();
    }

    // For testing only.  Index is zero-based.
    const SkFlatData* operator[](int index) {
        return fIndexedData[index];
    }

    /**
     * Given an element of type T return its 1-based index in the dictionary. If
     * the element wasn't previously in the dictionary it is automatically
     * added.
     *
     */
    int find(const T& element) {
        return this->findAndReturnFlat(element)->index();
    }

    /**
     * Similar to find. Allows the caller to specify an SkFlatData to replace in
     * the case of an add. Also tells the caller whether a new SkFlatData was
     * added and whether the old one was replaced. The parameters added and
     * replaced are required to be non-NULL. Rather than returning the index of
     * the entry in the dictionary, it returns the actual SkFlatData.
     */
    const SkFlatData* findAndReplace(const T& element,
                                     const SkFlatData* toReplace,
                                     bool* added,
                                     bool* replaced) {
        SkASSERT(added != NULL && replaced != NULL);

        const int oldCount = this->count();
        SkFlatData* flat = this->findAndReturnMutableFlat(element);
        *added = this->count() > oldCount;

        // If we don't want to replace anything, we're done.
        if (!*added || toReplace == NULL) {
            *replaced = false;
            return flat;
        }

        // If we don't have the thing to replace, we're done.
        const SkFlatData* found = fHash.find(*toReplace);
        if (found == NULL) {
            *replaced = false;
            return flat;
        }

        // findAndReturnMutableFlat put flat at the back.  Swap it into found->index() instead.
        // indices in SkFlatData are 1-based, while fIndexedData is 0-based.  Watch out!
        SkASSERT(flat->index() == this->count());
        flat->setIndex(found->index());
        fIndexedData.removeShuffle(found->index()-1);
        SkASSERT(flat == fIndexedData[found->index()-1]);

        // findAndReturnMutableFlat already called fHash.add(), so we just clean up the old entry.
        fHash.remove(*found);
        fController->unalloc((void*)found);
        SkASSERT(this->count() == oldCount);

        *replaced = true;
        return flat;
    }

    /**
     *  Unflatten the objects and return them in SkTRefArray, or return NULL
     *  if there no objects.  Caller takes ownership of result.
     */
    SkTRefArray<T>* unflattenToArray() const {
        const int count = this->count();
        if (count == 0) {
            return NULL;
        }
        SkTRefArray<T>* array = SkTRefArray<T>::Create(count);
        for (int i = 0; i < count; i++) {
            this->unflatten(&array->writableAt(i), fIndexedData[i]);
        }
        return array;
    }

    /**
     * Unflatten the specific object at the given index.
     * Caller takes ownership of the result.
     */
    T* unflatten(int index) const {
        // index is 1-based, while fIndexedData is 0-based.
        const SkFlatData* element = fIndexedData[index-1];
        SkASSERT(index == element->index());

        T* dst = new T;
        this->unflatten(dst, element);
        return dst;
    }

    /**
     * Find or insert a flattened version of element into the dictionary.
     * Caller does not take ownership of the result.  This will not return NULL.
     */
    const SkFlatData* findAndReturnFlat(const T& element) {
        return this->findAndReturnMutableFlat(element);
    }

private:
    // We have to delay fScratch's initialization until its first use; fController might not
    // be fully set up by the time we get it in the constructor.
    void lazyInit() {
        if (fReady) {
            return;
        }

        // Without a bitmap heap, we'll flatten bitmaps into paints.  That's never what you want.
        SkASSERT(fController->getBitmapHeap() != NULL);
        fScratch.setBitmapHeap(fController->getBitmapHeap());
        fScratch.setTypefaceRecorder(fController->getTypefaceSet());
        fScratch.setNamedFactoryRecorder(fController->getNamedFactorySet());
        fReady = true;
    }

    // As findAndReturnFlat, but returns a mutable pointer for internal use.
    SkFlatData* findAndReturnMutableFlat(const T& element) {
        // Only valid until the next call to resetScratch().
        const SkFlatData& scratch = this->resetScratch(element, this->count()+1);

        SkFlatData* candidate = fHash.find(scratch);
        if (candidate != NULL) {
            return candidate;
        }

        SkFlatData* detached = this->detachScratch();
        fHash.add(detached);
        *fIndexedData.append() = detached;
        SkASSERT(fIndexedData.top()->index() == this->count());
        return detached;
    }

    // This reference is valid only until the next call to resetScratch() or detachScratch().
    const SkFlatData& resetScratch(const T& element, int index) {
        this->lazyInit();

        // Layout of fScratch: [ SkFlatData header, 20 bytes ] [ data ..., 4-byte aligned ]
        fScratch.reset();
        fScratch.reserve(sizeof(SkFlatData));
        Traits::Flatten(fScratch, element);
        const size_t dataSize = fScratch.bytesWritten() - sizeof(SkFlatData);

        // Reinterpret data in fScratch as an SkFlatData.
        SkFlatData* scratch = (SkFlatData*)fScratch.getWriter32()->contiguousArray();
        SkASSERT(scratch != NULL);
        scratch->stampHeader(index, SkToS32(dataSize));
        return *scratch;
    }

    // This result is owned by fController and lives as long as it does (unless unalloc'd).
    SkFlatData* detachScratch() {
        // Allocate a new SkFlatData exactly big enough to hold our current scratch.
        // We use the controller for this allocation to extend the allocation's lifetime and allow
        // the controller to do whatever memory management it wants.
        SkFlatData* detached = (SkFlatData*)fController->allocThrow(fScratch.bytesWritten());

        // Copy scratch into the new SkFlatData.
        SkFlatData* scratch = (SkFlatData*)fScratch.getWriter32()->contiguousArray();
        SkASSERT(scratch != NULL);
        memcpy(detached, scratch, fScratch.bytesWritten());

        // We can now reuse fScratch, and detached will live until fController dies.
        return detached;
    }

    void unflatten(T* dst, const SkFlatData* element) const {
        element->unflatten<Traits>(dst,
                                   fController->getBitmapHeap(),
                                   fController->getTypefacePlayback());
    }

    // All SkFlatData* stored in fIndexedData and fHash are owned by the controller.
    SkAutoTUnref<SkFlatController> fController;
    SkWriteBuffer fScratch;
    bool fReady;

    // For index -> SkFlatData.  0-based, while all indices in the API are 1-based.  Careful!
    SkTDArray<const SkFlatData*> fIndexedData;

    // For SkFlatData -> cached SkFlatData, which has index().
    SkTDynamicHash<SkFlatData, SkFlatData, SkFlatData::HashTraits> fHash;
};

struct SkPaintFlatteningTraits {
    static void Flatten(SkWriteBuffer& buffer, const SkPaint& paint) { paint.flatten(buffer); }
    static void Unflatten(SkReadBuffer& buffer, SkPaint* paint) { paint->unflatten(buffer); }
};

typedef SkFlatDictionary<SkPaint, SkPaintFlatteningTraits> SkPaintDictionary;

class SkChunkFlatController : public SkFlatController {
public:
    SkChunkFlatController(size_t minSize)
    : fHeap(minSize)
    , fTypefaceSet(SkNEW(SkRefCntSet))
    , fLastAllocated(NULL) {
        this->setTypefaceSet(fTypefaceSet);
        this->setTypefacePlayback(&fTypefacePlayback);
    }

    virtual void* allocThrow(size_t bytes) SK_OVERRIDE {
        fLastAllocated = fHeap.allocThrow(bytes);
        return fLastAllocated;
    }

    virtual void unalloc(void* ptr) SK_OVERRIDE {
        // fHeap can only free a pointer if it was the last one allocated.  Otherwise, we'll just
        // have to wait until fHeap is destroyed.
        if (ptr == fLastAllocated) (void)fHeap.unalloc(ptr);
    }

    void setupPlaybacks() const {
        fTypefacePlayback.reset(fTypefaceSet.get());
    }

    void setBitmapStorage(SkBitmapHeap* heap) {
        this->setBitmapHeap(heap);
    }

private:
    SkChunkAlloc               fHeap;
    SkAutoTUnref<SkRefCntSet>  fTypefaceSet;
    void*                      fLastAllocated;
    mutable SkTypefacePlayback fTypefacePlayback;
};

#endif
