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

#include "GrPictureUtils.h"

#include "SkPaintPriv.h"
#include "SkRecord.h"
#include "SkRecords.h"

SkPicture::AccelData::Key GrAccelData::ComputeAccelDataKey() {
    static const SkPicture::AccelData::Key gGPUID = SkPicture::AccelData::GenerateDomain();

    return gGPUID;
}

// SkRecord visitor to gather saveLayer/restore information.
class CollectLayers {
public:
    CollectLayers(const SkPicture* pict, GrAccelData* accelData)
        : fPictureID(pict->uniqueID())
        , fCTM(&SkMatrix::I())
        , fSaveLayersInStack(0)
        , fAccelData(accelData) {

        pict->cullRect().roundOut(&fCurrentClipBounds);

        if (NULL == pict->fRecord.get()) {
            return;
        }

        for (fCurrentOp = 0; fCurrentOp < pict->fRecord->count(); ++fCurrentOp) {
            pict->fRecord->visit<void>(fCurrentOp, *this);
        }

        while (!fSaveStack.isEmpty()) {
            this->popSaveBlock();
        }
    }

    template <typename T> void operator()(const T& op) {
        this->updateCTM(op);
        this->updateClipBounds(op);
        this->trackSaveLayers(op);
    }

private:

    class SaveInfo {
    public:
        SaveInfo() { }
        SaveInfo(int opIndex, bool isSaveLayer, const SkPaint* paint, const SkIRect& bounds) 
            : fStartIndex(opIndex)
            , fIsSaveLayer(isSaveLayer)
            , fHasNestedSaveLayer(false)
            , fPaint(paint)
            , fBounds(bounds) {

        }

        int            fStartIndex;
        bool           fIsSaveLayer;
        bool           fHasNestedSaveLayer;
        const SkPaint* fPaint;
        SkIRect        fBounds;
    };

    uint32_t            fPictureID;
    unsigned int        fCurrentOp;
    const SkMatrix*     fCTM;
    SkIRect             fCurrentClipBounds;
    int                 fSaveLayersInStack;
    SkTDArray<SaveInfo> fSaveStack;
    GrAccelData*        fAccelData;

    template <typename T> void updateCTM(const T&) { /* most ops don't change the CTM */ }
    void updateCTM(const SkRecords::Restore& op)   { fCTM = &op.matrix; }
    void updateCTM(const SkRecords::SetMatrix& op) { fCTM = &op.matrix; }

    template <typename T> void updateClipBounds(const T&) { /* most ops don't change the clip */ }
    // Each of these devBounds fields is the state of the device bounds after the op.
    // So Restore's devBounds are those bounds saved by its paired Save or SaveLayer.
    void updateClipBounds(const SkRecords::Restore& op)    { fCurrentClipBounds = op.devBounds; }
    void updateClipBounds(const SkRecords::ClipPath& op)   { fCurrentClipBounds = op.devBounds; }
    void updateClipBounds(const SkRecords::ClipRRect& op)  { fCurrentClipBounds = op.devBounds; }
    void updateClipBounds(const SkRecords::ClipRect& op)   { fCurrentClipBounds = op.devBounds; }
    void updateClipBounds(const SkRecords::ClipRegion& op) { fCurrentClipBounds = op.devBounds; }
    void updateClipBounds(const SkRecords::SaveLayer& op)  {
        if (NULL != op.bounds) {
            fCurrentClipBounds.intersect(this->adjustAndMap(*op.bounds, op.paint));
        }
    }

    template <typename T> void trackSaveLayers(const T& op) { 
        /* most ops aren't involved in saveLayers */ 
    }
    void trackSaveLayers(const SkRecords::Save& s) { this->pushSaveBlock(); }
    void trackSaveLayers(const SkRecords::SaveLayer& sl) { this->pushSaveLayerBlock(sl.paint); }
    void trackSaveLayers(const SkRecords::Restore& r) { this->popSaveBlock(); }
    void trackSaveLayers(const SkRecords::DrawPicture& dp) {
        // For sub-pictures, we wrap their layer information within the parent
        // picture's rendering hierarchy
        const GrAccelData* childData = GPUOptimize(dp.picture);

        for (int i = 0; i < childData->numSaveLayers(); ++i) {
            const GrAccelData::SaveLayerInfo& src = childData->saveLayerInfo(i);

            this->updateStackForSaveLayer();

            GrAccelData::SaveLayerInfo dst;

            // TODO: need to store an SkRect in GrAccelData::SaveLayerInfo?
            SkRect srcRect = SkRect::MakeXYWH(SkIntToScalar(src.fOffset.fX),
                                              SkIntToScalar(src.fOffset.fY),
                                              SkIntToScalar(src.fSize.width()),
                                              SkIntToScalar(src.fSize.height()));
            SkIRect newClip(fCurrentClipBounds);
            newClip.intersect(this->adjustAndMap(srcRect, dp.paint));

            dst.fValid = true;
            dst.fPictureID = dp.picture->uniqueID();
            dst.fSize = SkISize::Make(newClip.width(), newClip.height());
            dst.fOffset = SkIPoint::Make(newClip.fLeft, newClip.fTop);
            dst.fOriginXform = *fCTM;
            dst.fOriginXform.postConcat(src.fOriginXform);
            dst.fOriginXform.postTranslate(SkIntToScalar(-newClip.fLeft), 
                                           SkIntToScalar(-newClip.fTop));

            if (NULL == src.fPaint) {
                dst.fPaint = NULL;
            } else {
                dst.fPaint = SkNEW_ARGS(SkPaint, (*src.fPaint));
            }

            dst.fSaveLayerOpID = src.fSaveLayerOpID;
            dst.fRestoreOpID = src.fRestoreOpID;
            dst.fHasNestedLayers = src.fHasNestedLayers;
            dst.fIsNested = fSaveLayersInStack > 0 || src.fIsNested;

            fAccelData->addSaveLayerInfo(dst);
        }
    }

    void pushSaveBlock() {
        fSaveStack.push(SaveInfo(fCurrentOp, false, NULL, SkIRect::MakeEmpty()));
    }

    // Inform all the saveLayers already on the stack that they now have a
    // nested saveLayer inside them
    void updateStackForSaveLayer() {
        for (int index = fSaveStack.count() - 1; index >= 0; --index) {
            if (fSaveStack[index].fHasNestedSaveLayer) {
                break;
            }
            fSaveStack[index].fHasNestedSaveLayer = true;
            if (fSaveStack[index].fIsSaveLayer) {
                break;
            }
        }
    }

    void pushSaveLayerBlock(const SkPaint* paint) {
        this->updateStackForSaveLayer();

        fSaveStack.push(SaveInfo(fCurrentOp, true, paint, fCurrentClipBounds));
        ++fSaveLayersInStack;
    }

    void popSaveBlock() {
        if (fSaveStack.count() <= 0) {
            SkASSERT(false);
            return;
        }

        SaveInfo si;
        fSaveStack.pop(&si);

        if (!si.fIsSaveLayer) {
            return;
        }

        --fSaveLayersInStack;

        GrAccelData::SaveLayerInfo slInfo;

        slInfo.fValid = true;
        slInfo.fPictureID = fPictureID;
        slInfo.fSize = SkISize::Make(si.fBounds.width(), si.fBounds.height());
        slInfo.fOffset = SkIPoint::Make(si.fBounds.fLeft, si.fBounds.fTop);
        slInfo.fOriginXform = *fCTM;
        slInfo.fOriginXform.postTranslate(SkIntToScalar(-si.fBounds.fLeft),
                                          SkIntToScalar(-si.fBounds.fTop));

        if (NULL == si.fPaint) {
            slInfo.fPaint = NULL;
        } else {
            slInfo.fPaint = SkNEW_ARGS(SkPaint, (*si.fPaint));
        }

        slInfo.fSaveLayerOpID = si.fStartIndex;
        slInfo.fRestoreOpID = fCurrentOp;
        slInfo.fHasNestedLayers = si.fHasNestedSaveLayer;
        slInfo.fIsNested = fSaveLayersInStack > 0;

        fAccelData->addSaveLayerInfo(slInfo);
    }

    // Returns true if rect was meaningfully adjusted for the effects of paint,
    // false if the paint could affect the rect in unknown ways.
    static bool AdjustForPaint(const SkPaint* paint, SkRect* rect) {
        if (paint) {
            if (paint->canComputeFastBounds()) {
                *rect = paint->computeFastBounds(*rect, rect);
                return true;
            }
            return false;
        }
        return true;
    }

    // Adjust rect for all paints that may affect its geometry, then map it to device space.
    SkIRect adjustAndMap(SkRect rect, const SkPaint* paint) const {
        // Inverted rectangles really confuse our BBHs.
        rect.sort();

        // Adjust the rect for its own paint.
        if (!AdjustForPaint(paint, &rect)) {
            // The paint could do anything to our bounds.  The only safe answer is the current clip.
            return fCurrentClipBounds;
        }

        // Adjust rect for all the paints from the SaveLayers we're inside.
        for (int i = fSaveStack.count() - 1; i >= 0; i--) {
            if (!AdjustForPaint(fSaveStack[i].fPaint, &rect)) {
                // Same deal as above.
                return fCurrentClipBounds;
            }
        }

        // Map the rect back to device space.
        fCTM->mapRect(&rect);
        SkIRect devRect;
        rect.roundOut(&devRect);

        // Nothing can draw outside the current clip.
        // (Only bounded ops call into this method, so oddballs like Clear don't matter here.)
        devRect.intersect(fCurrentClipBounds);
        return devRect;
    }
};


// GPUOptimize is only intended to be called within the context of SkGpuDevice's
// EXPERIMENTAL_optimize method.
const GrAccelData* GPUOptimize(const SkPicture* pict) {
    if (NULL == pict || pict->cullRect().isEmpty()) {
        return NULL;
    }

    SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey();

    const GrAccelData* existing = 
                            static_cast<const GrAccelData*>(pict->EXPERIMENTAL_getAccelData(key));
    if (NULL != existing) {
        return existing;
    }

    SkAutoTUnref<GrAccelData> data(SkNEW_ARGS(GrAccelData, (key)));

    pict->EXPERIMENTAL_addAccelData(data);

    CollectLayers collector(pict, data);

    return data;
}
