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

#include "SkPictureUtils.h"
#include "SkCanvas.h"
#include "SkData.h"
#include "SkDevice.h"
#include "SkPixelRef.h"
#include "SkShader.h"
#include "SkRRect.h"

class PixelRefSet {
public:
    PixelRefSet(SkTDArray<SkPixelRef*>* array) : fArray(array) {}

    // This does a linear search on existing pixelrefs, so if this list gets big
    // we should use a more complex sorted/hashy thing.
    //
    void add(SkPixelRef* pr) {
        uint32_t genID = pr->getGenerationID();
        if (fGenID.find(genID) < 0) {
            *fArray->append() = pr;
            *fGenID.append() = genID;
//            SkDebugf("--- adding [%d] %x %d\n", fArray->count() - 1, pr, genID);
        } else {
//            SkDebugf("--- already have %x %d\n", pr, genID);
        }
    }

private:
    SkTDArray<SkPixelRef*>* fArray;
    SkTDArray<uint32_t>     fGenID;
};

static void not_supported() {
    SkASSERT(!"this method should never be called");
}

static void nothing_to_do() {}

/**
 *  This device will route all bitmaps (primitives and in shaders) to its PRSet.
 *  It should never actually draw anything, so there need not be any pixels
 *  behind its device-bitmap.
 */
class GatherPixelRefDevice : public SkDevice {
private:
    PixelRefSet*  fPRSet;

    void addBitmap(const SkBitmap& bm) {
        fPRSet->add(bm.pixelRef());
    }

    void addBitmapFromPaint(const SkPaint& paint) {
        SkShader* shader = paint.getShader();
        if (shader) {
            SkBitmap bm;
            // Check whether the shader is a gradient in order to short-circuit
            // call to asABitmap to prevent generation of bitmaps from
            // gradient shaders, which implement asABitmap.
            if (SkShader::kNone_GradientType == shader->asAGradient(NULL) &&
                shader->asABitmap(&bm, NULL, NULL)) {
                fPRSet->add(bm.pixelRef());
            }
        }
    }

public:
    GatherPixelRefDevice(const SkBitmap& bm, PixelRefSet* prset) : SkDevice(bm) {
        fPRSet = prset;
    }

    virtual void clear(SkColor color) SK_OVERRIDE {
        nothing_to_do();
    }
    virtual void writePixels(const SkBitmap& bitmap, int x, int y,
                             SkCanvas::Config8888 config8888) SK_OVERRIDE {
        not_supported();
    }

    virtual void drawPaint(const SkDraw&, const SkPaint& paint) SK_OVERRIDE {
        this->addBitmapFromPaint(paint);
    }
    virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode, size_t count,
                            const SkPoint[], const SkPaint& paint) SK_OVERRIDE {
        this->addBitmapFromPaint(paint);
    }
    virtual void drawRect(const SkDraw&, const SkRect&,
                          const SkPaint& paint) SK_OVERRIDE {
        this->addBitmapFromPaint(paint);
    }
    virtual void drawOval(const SkDraw&, const SkRect&,
                          const SkPaint& paint) SK_OVERRIDE {
        this->addBitmapFromPaint(paint);
    }
    virtual void drawPath(const SkDraw&, const SkPath& path,
                          const SkPaint& paint, const SkMatrix* prePathMatrix,
                          bool pathIsMutable) SK_OVERRIDE {
        this->addBitmapFromPaint(paint);
    }
    virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap,
                            const SkIRect* srcRectOrNull,
                            const SkMatrix&, const SkPaint&) SK_OVERRIDE {
        this->addBitmap(bitmap);
    }
    virtual void drawBitmapRect(const SkDraw&, const SkBitmap& bitmap,
                                const SkRect* srcOrNull, const SkRect& dst,
                                const SkPaint&) SK_OVERRIDE {
        this->addBitmap(bitmap);
    }
    virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
                            int x, int y, const SkPaint& paint) SK_OVERRIDE {
        this->addBitmap(bitmap);
    }
    virtual void drawText(const SkDraw&, const void* text, size_t len,
                          SkScalar x, SkScalar y,
                          const SkPaint& paint) SK_OVERRIDE {
        this->addBitmapFromPaint(paint);
    }
    virtual void drawPosText(const SkDraw&, const void* text, size_t len,
                             const SkScalar pos[], SkScalar constY,
                             int, const SkPaint& paint) SK_OVERRIDE {
        this->addBitmapFromPaint(paint);
    }
    virtual void drawTextOnPath(const SkDraw&, const void* text, size_t len,
                                const SkPath& path, const SkMatrix* matrix,
                                const SkPaint& paint) SK_OVERRIDE {
        this->addBitmapFromPaint(paint);
    }
    virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCount,
                              const SkPoint verts[], const SkPoint texs[],
                              const SkColor colors[], SkXfermode* xmode,
                              const uint16_t indices[], int indexCount,
                              const SkPaint& paint) SK_OVERRIDE {
        this->addBitmapFromPaint(paint);
    }
    virtual void drawDevice(const SkDraw&, SkDevice*, int x, int y,
                            const SkPaint&) SK_OVERRIDE {
        nothing_to_do();
    }

protected:
    virtual bool onReadPixels(const SkBitmap& bitmap,
                              int x, int y,
                              SkCanvas::Config8888 config8888) SK_OVERRIDE {
        not_supported();
        return false;
    }
};

class NoSaveLayerCanvas : public SkCanvas {
public:
    NoSaveLayerCanvas(SkDevice* device) : INHERITED(device) {}

    // turn saveLayer() into save() for speed, should not affect correctness.
    virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
                          SaveFlags flags) SK_OVERRIDE {

        // Like SkPictureRecord, we don't want to create layers, but we do need
        // to respect the save and (possibly) its rect-clip.

        int count = this->INHERITED::save(flags);
        if (bounds) {
            this->INHERITED::clipRectBounds(bounds, flags, NULL);
        }
        return count;
    }

    // disable aa for speed
    virtual bool clipRect(const SkRect& rect, SkRegion::Op op,
                          bool doAA) SK_OVERRIDE {
        return this->INHERITED::clipRect(rect, op, false);
    }

    // for speed, just respect the bounds, and disable AA. May give us a few
    // false positives and negatives.
    virtual bool clipPath(const SkPath& path, SkRegion::Op op,
                          bool doAA) SK_OVERRIDE {
        return this->INHERITED::clipRect(path.getBounds(), op, false);
    }
    virtual bool clipRRect(const SkRRect& rrect, SkRegion::Op op,
                           bool doAA) SK_OVERRIDE {
        return this->INHERITED::clipRect(rrect.getBounds(), op, false);
    }

private:
    typedef SkCanvas INHERITED;
};

SkData* SkPictureUtils::GatherPixelRefs(SkPicture* pict, const SkRect& area) {
    if (NULL == pict) {
        return NULL;
    }

    // this test also handles if either area or pict's width/height are empty
    if (!SkRect::Intersects(area,
                            SkRect::MakeWH(SkIntToScalar(pict->width()),
                                           SkIntToScalar(pict->height())))) {
        return NULL;
    }

    SkTDArray<SkPixelRef*> array;
    PixelRefSet prset(&array);

    SkBitmap emptyBitmap;
    emptyBitmap.setConfig(SkBitmap::kARGB_8888_Config, pict->width(), pict->height());
    // note: we do not set any pixels (shouldn't need to)

    GatherPixelRefDevice device(emptyBitmap, &prset);
    NoSaveLayerCanvas canvas(&device);

    canvas.clipRect(area, SkRegion::kIntersect_Op, false);
    canvas.drawPicture(*pict);

    SkData* data = NULL;
    int count = array.count();
    if (count > 0) {
        data = SkData::NewFromMalloc(array.detach(), count * sizeof(SkPixelRef*));
    }
    return data;
}
