/*
 * 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 (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 (existing) {
        return existing;
    }

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

    pict->EXPERIMENTAL_addAccelData(data);

    CollectLayers collector(pict, data);

    return data;
}
