/*
 * 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 SkGatherPixelRefsAndRects_DEFINED
#define SkGatherPixelRefsAndRects_DEFINED

#include "SkBitmap.h"
#include "SkDevice.h"
#include "SkDraw.h"
#include "SkPictureUtils.h"
#include "SkRasterClip.h"
#include "SkRefCnt.h"
#include "SkRRect.h"
#include "SkTypes.h"

// This GatherPixelRefs device passes all discovered pixel refs and their
// device bounds to the user provided SkPixelRefContainer-derived object
class SkGatherPixelRefsAndRectsDevice : public SkBaseDevice {
public:
    SK_DECLARE_INST_COUNT(SkGatherPixelRefsAndRectsDevice)

    SkGatherPixelRefsAndRectsDevice(int width, int height, 
                                    SkPictureUtils::SkPixelRefContainer* prCont) {
        fSize.set(width, height);
        fPRCont = prCont;
        SkSafeRef(fPRCont);
        fEmptyBitmap.setConfig(SkBitmap::kNo_Config, width, height);
    }

    virtual ~SkGatherPixelRefsAndRectsDevice() {
        SkSafeUnref(fPRCont);
    }

    virtual uint32_t getDeviceCapabilities() SK_OVERRIDE { return 0; }

    virtual int width() const SK_OVERRIDE { return fSize.width(); }
    virtual int height() const SK_OVERRIDE { return fSize.height(); }
    virtual bool isOpaque() const SK_OVERRIDE { return false; }
    virtual SkBitmap::Config config() const SK_OVERRIDE {
        return SkBitmap::kNo_Config;
    }
    virtual void writePixels(const SkBitmap& bitmap, int x, int y,
                             SkCanvas::Config8888 config8888) SK_OVERRIDE {
        NotSupported();
    }
    virtual GrRenderTarget* accessRenderTarget() SK_OVERRIDE { return NULL; }

protected:
    virtual bool filterTextFlags(const SkPaint& paint, TextFlags*) SK_OVERRIDE {
        return false;
    }
    virtual void clear(SkColor color) SK_OVERRIDE {
        NothingToDo();
    }
    virtual void drawPaint(const SkDraw& draw, const SkPaint& paint) SK_OVERRIDE {
        SkBitmap bm;

        if (GetBitmapFromPaint(paint, &bm)) {
            SkRect clipRect = SkRect::Make(draw.fRC->getBounds());
            fPRCont->add(bm.pixelRef(), clipRect);
        }
    }
    virtual void drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t count,
                            const SkPoint points[], const SkPaint& paint) SK_OVERRIDE {
        SkBitmap bm;
        if (!GetBitmapFromPaint(paint, &bm)) {
            return;
        }

        if (0 == count) {
            return;
        }

        SkPoint min = points[0];
        SkPoint max = points[0];
        for (size_t i = 1; i < count; ++i) {
            const SkPoint& point = points[i];

            min.set(SkMinScalar(min.x(), point.x()), SkMinScalar(min.y(), point.y()));
            max.set(SkMaxScalar(max.x(), point.x()), SkMaxScalar(max.y(), point.y()));
        }

        SkRect bounds = SkRect::MakeLTRB(min.x(), min.y(), max.x()+1, max.y()+1);

        this->drawRect(draw, bounds, paint);
    }
    virtual void drawRect(const SkDraw& draw, const SkRect& rect,
                          const SkPaint& paint) SK_OVERRIDE {
        SkBitmap bm;
        if (GetBitmapFromPaint(paint, &bm)) {
            SkRect mappedRect;
            draw.fMatrix->mapRect(&mappedRect, rect);
            SkRect clipRect = SkRect::Make(draw.fRC->getBounds());
            mappedRect.intersect(clipRect);
            fPRCont->add(bm.pixelRef(), mappedRect);
        }
    }
    virtual void drawOval(const SkDraw& draw, const SkRect& rect,
                          const SkPaint& paint) SK_OVERRIDE {
        this->drawRect(draw, rect, paint);
    }
    virtual void drawRRect(const SkDraw& draw, const SkRRect& rrect,
                           const SkPaint& paint) SK_OVERRIDE {
        this->drawRect(draw, rrect.rect(), paint);
    }
    virtual void drawPath(const SkDraw& draw, const SkPath& path,
                          const SkPaint& paint, const SkMatrix* prePathMatrix,
                          bool pathIsMutable) SK_OVERRIDE {
        SkBitmap bm;
        if (!GetBitmapFromPaint(paint, &bm)) {
            return;
        }

        SkRect pathBounds = path.getBounds();
        if (NULL != prePathMatrix) {
            prePathMatrix->mapRect(&pathBounds);
        } 

        this->drawRect(draw, pathBounds, paint);
    }
    virtual void drawBitmap(const SkDraw& draw, const SkBitmap& bitmap,
                            const SkMatrix& matrix, const SkPaint& paint) SK_OVERRIDE {
        SkMatrix totMatrix;
        totMatrix.setConcat(*draw.fMatrix, matrix);

        SkRect bitmapRect = SkRect::MakeWH(SkIntToScalar(bitmap.width()), 
                                           SkIntToScalar(bitmap.height()));
        SkRect mappedRect;
        totMatrix.mapRect(&mappedRect, bitmapRect);
        fPRCont->add(bitmap.pixelRef(), mappedRect);

        SkBitmap paintBitmap;
        if (GetBitmapFromPaint(paint, &paintBitmap)) {
            fPRCont->add(paintBitmap.pixelRef(), mappedRect);
        }
    }
    virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
                            int x, int y, const SkPaint& paint) SK_OVERRIDE {
        // Sprites aren't affected by current matrix, so we can't reuse drawRect.
        SkMatrix matrix;
        matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y));

        SkRect bitmapRect = SkRect::MakeWH(SkIntToScalar(bitmap.width()), 
                                           SkIntToScalar(bitmap.height()));
        SkRect mappedRect;
        matrix.mapRect(&mappedRect, bitmapRect);
        fPRCont->add(bitmap.pixelRef(), mappedRect);

        SkBitmap paintBitmap;
        if (GetBitmapFromPaint(paint, &paintBitmap)) {
            fPRCont->add(paintBitmap.pixelRef(), mappedRect);
        }
    }
    virtual void drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
                                const SkRect* srcOrNull, const SkRect& dst,
                                const SkPaint& paint,
                                SkCanvas::DrawBitmapRectFlags flags) SK_OVERRIDE {
        SkRect bitmapRect = SkRect::MakeWH(SkIntToScalar(bitmap.width()), 
                                           SkIntToScalar(bitmap.height()));
        SkMatrix matrix;
        matrix.setRectToRect(bitmapRect, dst, SkMatrix::kFill_ScaleToFit);
        this->drawBitmap(draw, bitmap, matrix, paint);
    }
    virtual void drawText(const SkDraw& draw, const void* text, size_t len,
                          SkScalar x, SkScalar y,
                          const SkPaint& paint) SK_OVERRIDE {
        SkBitmap bitmap;
        if (!GetBitmapFromPaint(paint, &bitmap)) {
            return;
        }

        // Math is borrowed from SkBBoxRecord
        SkRect bounds;
        paint.measureText(text, len, &bounds);
        SkPaint::FontMetrics metrics;
        paint.getFontMetrics(&metrics);

        if (paint.isVerticalText()) {
            SkScalar h = bounds.fBottom - bounds.fTop;
            if (paint.getTextAlign() == SkPaint::kCenter_Align) {
                bounds.fTop -= h / 2;
                bounds.fBottom -= h / 2;
            }
            bounds.fBottom += metrics.fBottom;
            bounds.fTop += metrics.fTop;
        } else {
            SkScalar w = bounds.fRight - bounds.fLeft;
            if (paint.getTextAlign() == SkPaint::kCenter_Align) {
                bounds.fLeft -= w / 2;
                bounds.fRight -= w / 2;
            } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
                bounds.fLeft -= w;
                bounds.fRight -= w;
            }
            bounds.fTop = metrics.fTop;
            bounds.fBottom = metrics.fBottom;
        }

        SkScalar pad = (metrics.fBottom - metrics.fTop) / 2;
        bounds.fLeft -= pad;
        bounds.fRight += pad;
        bounds.offset(x, y);

        this->drawRect(draw, bounds, paint);
    }
    virtual void drawPosText(const SkDraw& draw, const void* text, size_t len,
                             const SkScalar pos[], SkScalar constY,
                             int scalarsPerPos, const SkPaint& paint) SK_OVERRIDE {
        SkBitmap bitmap;
        if (!GetBitmapFromPaint(paint, &bitmap)) {
            return;
        }

        if (0 == len) {
            return;
        }

        // Similar to SkDraw asserts.
        SkASSERT(scalarsPerPos == 1 || scalarsPerPos == 2);

        SkPoint min, max;
        if (1 == scalarsPerPos) {
            min.set(pos[0], constY);
            max.set(pos[0], constY);
        } else if (2 == scalarsPerPos) {
            min.set(pos[0], constY + pos[1]);
            max.set(pos[0], constY + pos[1]);
        }

        for (size_t i = 1; i < len; ++i) {
            SkScalar x = pos[i * scalarsPerPos];
            SkScalar y = constY;
            if (2 == scalarsPerPos) {
                y += pos[i * scalarsPerPos + 1];
            }

            min.set(SkMinScalar(x, min.x()), SkMinScalar(y, min.y()));
            max.set(SkMaxScalar(x, max.x()), SkMaxScalar(y, max.y()));
        }

        SkRect bounds = SkRect::MakeLTRB(min.x(), min.y(), max.x(), max.y());

        // Math is borrowed from SkBBoxRecord
        SkPaint::FontMetrics metrics;
        paint.getFontMetrics(&metrics);

        bounds.fTop += metrics.fTop;
        bounds.fBottom += metrics.fBottom;

        SkScalar pad = (metrics.fTop - metrics.fBottom) / 2;
        bounds.fLeft -= pad;
        bounds.fRight += pad;

        this->drawRect(draw, bounds, paint);
    }
    virtual void drawTextOnPath(const SkDraw& draw, const void* text, size_t len,
                                const SkPath& path, const SkMatrix* matrix,
                                const SkPaint& paint) SK_OVERRIDE {
        SkBitmap bitmap;
        if (!GetBitmapFromPaint(paint, &bitmap)) {
            return;
        }

        // Math is borrowed from SkBBoxRecord
        SkRect bounds = path.getBounds();
        SkPaint::FontMetrics metrics;
        paint.getFontMetrics(&metrics);

        SkScalar pad = metrics.fTop;
        // TODO: inset?!
        bounds.fLeft += pad;
        bounds.fRight -= pad;
        bounds.fTop += pad;
        bounds.fBottom -= pad;

        this->drawRect(draw, bounds, paint);
    }
    virtual void drawVertices(const SkDraw& draw, 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->drawPoints(draw, SkCanvas::kPolygon_PointMode, vertexCount, verts, paint);                                    
    }
    virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y,
                            const SkPaint&) SK_OVERRIDE {
        NothingToDo();
    }
    // TODO: allow this call to return failure, or move to SkBitmapDevice only.
    virtual const SkBitmap& onAccessBitmap() SK_OVERRIDE {
        return fEmptyBitmap;
    }
    virtual bool onReadPixels(const SkBitmap& bitmap,
                              int x, int y,
                              SkCanvas::Config8888 config8888) SK_OVERRIDE {
        NotSupported();
        return false;
    }
    virtual void lockPixels() SK_OVERRIDE { NothingToDo(); }
    virtual void unlockPixels() SK_OVERRIDE { NothingToDo(); }
    virtual bool allowImageFilter(SkImageFilter*) SK_OVERRIDE { return false; }
    virtual bool canHandleImageFilter(SkImageFilter*) SK_OVERRIDE { return false; }
    virtual bool filterImage(SkImageFilter*, const SkBitmap&, const SkMatrix&,
                             SkBitmap* result, SkIPoint* offset) SK_OVERRIDE {
        return false;
    }

private:
    SkPictureUtils::SkPixelRefContainer* fPRCont;
    SkISize                              fSize;

    SkBitmap                             fEmptyBitmap; // legacy -- need to remove

    static bool GetBitmapFromPaint(const SkPaint &paint, SkBitmap* bitmap) {
        SkShader* shader = paint.getShader();
        if (NULL != shader) {
            if (SkShader::kNone_GradientType == shader->asAGradient(NULL)) {
                return SkShader::kNone_BitmapType != shader->asABitmap(bitmap, NULL, NULL);
            }
        }
        return false;
    }

    virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) SK_OVERRIDE {
        NotSupported();
    }

    virtual SkBaseDevice* onCreateCompatibleDevice(SkBitmap::Config config,
                                                   int width, int height,
                                                   bool isOpaque,
                                                   Usage usage) SK_OVERRIDE {
        // we expect to only get called via savelayer, in which case it is fine.
        SkASSERT(kSaveLayer_Usage == usage);
        return SkNEW_ARGS(SkGatherPixelRefsAndRectsDevice, (width, height, fPRCont));
    }

    virtual void flush() SK_OVERRIDE {}

    static void NotSupported() {
        SkDEBUGFAIL("this method should never be called");
    }

    static void NothingToDo() {}

    typedef SkBaseDevice INHERITED;
};

#endif // SkGatherPixelRefsAndRects_DEFINED

