/*
 * 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 "include/core/SkBBHFactory.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkBlendMode.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkImage.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPicture.h"
#include "include/core/SkPictureRecorder.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSamplingOptions.h"
#include "include/core/SkScalar.h"
#include "include/core/SkString.h"
#include "include/core/SkSurface.h"
#include "tests/Test.h"

#include <cstring>

// Verify that replay of a recording into a clipped canvas
// produces the correct bitmap.
// This arose from http://crbug.com/401593 which has
// https://code.google.com/p/skia/issues/detail?id=1291 as its root cause.

namespace {

class Drawer {
 public:
    explicit Drawer() : fImageInfo(SkImageInfo::MakeN32Premul(200, 100)) {
        auto surf = SkSurface::MakeRasterN32Premul(100, 100);
        surf->getCanvas()->clear(0xffffffff);
        SkPaint circlePaint;
        circlePaint.setColor(0xff000000);
        surf->getCanvas()->drawCircle(50, 50, 50, circlePaint);
        fCircleImage = surf->makeImageSnapshot();
    }

    const SkImageInfo& imageInfo() const { return fImageInfo; }

    void draw(SkCanvas* canvas, const SkRect& clipRect, SkBlendMode mode) const {
        SkPaint greenPaint;
        greenPaint.setColor(0xff008000);
        SkPaint blackPaint;
        blackPaint.setColor(0xff000000);
        SkPaint whitePaint;
        whitePaint.setColor(0xffffffff);
        SkPaint layerPaint;
        layerPaint.setColor(0xff000000);
        layerPaint.setBlendMode(mode);
        SkRect canvasRect(SkRect::MakeWH(SkIntToScalar(fImageInfo.width()),
                                         SkIntToScalar(fImageInfo.height())));

        canvas->clipRect(clipRect);
        canvas->clear(0xff000000);

        canvas->saveLayer(nullptr, &blackPaint);
            canvas->drawRect(canvasRect, greenPaint);
            canvas->saveLayer(nullptr, &layerPaint);
                canvas->drawImageRect(fCircleImage, SkRect::MakeXYWH(20,20,60,60),
                                      SkSamplingOptions(), &blackPaint);
            canvas->restore();
        canvas->restore();
    }

 private:
    const SkImageInfo fImageInfo;
    sk_sp<SkImage> fCircleImage;
};

class RecordingStrategy {
 public:
    virtual ~RecordingStrategy() {}
    virtual const SkBitmap& recordAndReplay(const Drawer& drawer,
                                            const SkRect& intoClip,
                                            SkBlendMode) = 0;
};

class BitmapBackedCanvasStrategy : public RecordingStrategy {
    // This version just draws into a bitmap-backed canvas.
 public:
    BitmapBackedCanvasStrategy(const SkImageInfo& imageInfo) {
        fBitmap.allocPixels(imageInfo);
    }

    const SkBitmap& recordAndReplay(const Drawer& drawer, const SkRect& intoClip,
                                    SkBlendMode mode) override {
        SkCanvas canvas(fBitmap);
        canvas.clear(0xffffffff);
        // Note that the scene is drawn just into the clipped region!
        canvas.clipRect(intoClip);
        drawer.draw(&canvas, intoClip, mode); // Shouild be canvas-wide...
        return fBitmap;
    }

 private:
    SkBitmap fBitmap;
};

class PictureStrategy : public RecordingStrategy {
    // This version draws the entire scene into an SkPictureRecorder.
    // Then it then replays the scene through a clip rectangle.
    // This backend proved to be buggy.
 public:
    PictureStrategy(const SkImageInfo& imageInfo) {
        fBitmap.allocPixels(imageInfo);
        fWidth  = imageInfo.width();
        fHeight = imageInfo.height();
    }

    const SkBitmap& recordAndReplay(const Drawer& drawer, const SkRect& intoClip,
                                    SkBlendMode mode) override {
        SkRTreeFactory factory;
        SkPictureRecorder recorder;
        SkRect canvasRect(SkRect::MakeWH(SkIntToScalar(fWidth),SkIntToScalar(fHeight)));
        SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(fWidth),
                                                   SkIntToScalar(fHeight),
                                                   &factory);
        drawer.draw(canvas, canvasRect, mode);
        sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());

        SkCanvas replayCanvas(fBitmap);
        replayCanvas.clear(0xffffffff);
        replayCanvas.clipRect(intoClip);
        picture->playback(&replayCanvas);
        return fBitmap;
    }

 private:
    SkBitmap fBitmap;
    int fWidth;
    int fHeight;
};

} // namespace


DEF_TEST(SkRecordingAccuracyXfermode, reporter) {
#define FINEGRAIN 0
    const Drawer drawer;

    BitmapBackedCanvasStrategy golden(drawer.imageInfo());
    PictureStrategy picture(drawer.imageInfo());

#if !FINEGRAIN
    unsigned numErrors = 0;
    SkString errors;
#endif

    for (int iMode = 0; iMode < kSkBlendModeCount; iMode++) {
        const SkRect& clip = SkRect::MakeXYWH(100, 0, 100, 100);
        SkBlendMode mode = SkBlendMode(iMode);

        const SkBitmap& goldenBM = golden.recordAndReplay(drawer, clip, mode);
        const SkBitmap& pictureBM = picture.recordAndReplay(drawer, clip, mode);

        size_t pixelsSize = goldenBM.computeByteSize();
        REPORTER_ASSERT(reporter, pixelsSize == pictureBM.computeByteSize());

        // The pixel arrays should match.
#if FINEGRAIN
        REPORTER_ASSERT(reporter,
                        0 == memcmp(goldenBM.getPixels(), pictureBM.getPixels(), pixelsSize));
#else
        if (0 != memcmp(goldenBM.getPixels(), pictureBM.getPixels(), pixelsSize)) {
            numErrors++;
            errors.appendf("For SkXfermode %d %s:    SkPictureRecorder bitmap is wrong\n",
                           iMode, SkBlendMode_Name(mode));
        }
#endif
    }

#if !FINEGRAIN
    REPORTER_ASSERT(reporter, 0 == numErrors, "%s", errors.c_str());
#endif
}
