/*
 * 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.setInfo(SkImageInfo::MakeUnknown(width, height));
    }

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

    virtual SkImageInfo imageInfo() const SK_OVERRIDE {
        return fEmptyBitmap.info();
    }

protected:
    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());
            if (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 (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[], int scalarsPerPos,
                             const SkPoint& offset, 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 = SkPoint::Make(offset.x() + pos[0],
                                    offset.y() + (2 == scalarsPerPos ? pos[1] : 0));
        SkPoint max = min;

        for (size_t i = 1; i < len; ++i) {
            SkScalar x = offset.x() + pos[i * scalarsPerPos];
            SkScalar y = offset.y() + (2 == scalarsPerPos ? pos[i * 2 + 1] : 0);

            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 void lockPixels() SK_OVERRIDE { NothingToDo(); }
    virtual void unlockPixels() SK_OVERRIDE { NothingToDo(); }
    virtual bool allowImageFilter(const SkImageFilter*) SK_OVERRIDE { return false; }
    virtual bool canHandleImageFilter(const SkImageFilter*) SK_OVERRIDE { return false; }
    virtual bool filterImage(const SkImageFilter*, const SkBitmap&, const SkImageFilter::Context&,
                             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 (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(const CreateInfo& info) SK_OVERRIDE {
        // we expect to only get called via savelayer, in which case it is fine.
        SkASSERT(kSaveLayer_Usage == info.fUsage);
        return SkNEW_ARGS(SkGatherPixelRefsAndRectsDevice,
                          (info.fInfo.width(), info.fInfo.height(), fPRCont));
    }

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

    static void NothingToDo() {}

    typedef SkBaseDevice INHERITED;
};

#endif // SkGatherPixelRefsAndRects_DEFINED
