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

#ifndef GrRecordReplaceDraw_DEFINED
#define GrRecordReplaceDraw_DEFINED

#include "SkChecksum.h"
#include "SkDrawPictureCallback.h"
#include "SkImage.h"
#include "SkRect.h"
#include "SkTDynamicHash.h"

class SkBBoxHierarchy;
class SkBitmap;
class SkCanvas;
class SkImage;
class SkMatrix;
class SkPaint;
class SkPicture;
class SkRecord;

// GrReplacements collects op ranges that can be replaced with
// a single drawBitmap call (using a precomputed bitmap).
class GrReplacements {
public:
    // All the operations between fStart and fStop (inclusive) will be replaced with
    // a single drawBitmap call using fPos, fImage and fPaint.
    class ReplacementInfo {
    public:
        struct Key {
            Key(uint32_t pictureID, unsigned start, const SkMatrix& ctm)
            : fPictureID(pictureID)
            , fStart(start)
            , fCTM(ctm) {
                fCTM.getType(); // force initialization of type so hashes match

                // Key needs to be tightly packed.
                GR_STATIC_ASSERT(sizeof(Key) == sizeof(uint32_t) +      // picture ID
                                                sizeof(int) +           // start
                                                9 * sizeof(SkScalar)    // 3x3 from CTM
                                                +sizeof(uint32_t));     // matrix's type
            }

            bool operator==(const Key& other) const { 
                return fPictureID == other.fPictureID &&
                       fStart == other.fStart &&
                       fCTM.cheapEqualTo(other.fCTM); // TODO: should be fuzzy
            }

            uint32_t     pictureID() const { return fPictureID; }
            unsigned int start() const { return fStart; }

        private:
            const uint32_t fPictureID;
            const unsigned fStart;
            const SkMatrix fCTM;
        };

        static const Key& GetKey(const ReplacementInfo& layer) { return layer.fKey; }
        static uint32_t Hash(const Key& key) {
            return SkChecksum::Murmur3(reinterpret_cast<const uint32_t*>(&key), sizeof(Key));
        }

        ReplacementInfo(uint32_t pictureID, unsigned int start, const SkMatrix& ctm)
            : fKey(pictureID, start, ctm)
            , fImage(NULL)
            , fPaint(NULL) {
        }
        ~ReplacementInfo() { fImage->unref(); SkDELETE(fPaint); }

        unsigned int start() const { return fKey.start(); }

        const Key       fKey;
        unsigned        fStop;
        SkIPoint        fPos;
        SkImage*        fImage;  // Owns a ref
        const SkPaint*  fPaint;  // Owned by this object

        SkIRect         fSrcRect;
    };

    ~GrReplacements() { this->freeAll(); }

    // Add a new replacement range.
    ReplacementInfo* newReplacement(uint32_t pictureID, unsigned start, const SkMatrix& ctm);

    // look up a replacement range by its pictureID, start offset and the CTM
    // TODO: also need to add clip to lookup
    const ReplacementInfo* lookupByStart(uint32_t pictureID, unsigned start, 
                                         const SkMatrix& ctm) const;

private:
    SkTDynamicHash<ReplacementInfo, ReplacementInfo::Key> fReplacementHash;

    void freeAll();
};

// Draw an SkPicture into an SkCanvas replacing saveLayer/restore blocks with
// drawBitmap calls.  A convenience wrapper around SkRecords::Draw.
// It returns the number of saveLayer/restore blocks replaced with drawBitmap calls.
int GrRecordReplaceDraw(const SkPicture*,
                        SkCanvas*,
                        const GrReplacements*,
                        const SkMatrix& initialMatrix,
                        SkDrawPictureCallback*);

#endif // GrRecordReplaceDraw_DEFINED
