/*
 * 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())
        , fCurrentClipBounds(SkIRect::MakeXYWH(0, 0, pict->width(), pict->height()))
        , fSaveLayersInStack(0)
        , fAccelData(accelData) {

        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 || 0 == pict->width() || 0 == pict->height()) {
        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;
}
