/*
 * 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 "tests/RecordTestUtils.h"
#include "tests/Test.h"

#include "include/core/SkColorFilter.h"
#include "include/core/SkPictureRecorder.h"
#include "include/core/SkSurface.h"
#include "include/effects/SkBlurImageFilter.h"
#include "include/effects/SkPictureImageFilter.h"
#include "src/core/SkRecord.h"
#include "src/core/SkRecordOpts.h"
#include "src/core/SkRecorder.h"
#include "src/core/SkRecords.h"

static const int W = 1920, H = 1080;

DEF_TEST(RecordOpts_NoopDraw, r) {
    SkRecord record;
    SkRecorder recorder(&record, W, H);

    recorder.drawRect(SkRect::MakeWH(200, 200), SkPaint());
    recorder.drawRect(SkRect::MakeWH(300, 300), SkPaint());
    recorder.drawRect(SkRect::MakeWH(100, 100), SkPaint());

    record.replace<SkRecords::NoOp>(1);  // NoOps should be allowed.

    SkRecordNoopSaveRestores(&record);

    REPORTER_ASSERT(r, 2 == count_instances_of_type<SkRecords::DrawRect>(record));
}

DEF_TEST(RecordOpts_SingleNoopSaveRestore, r) {
    SkRecord record;
    SkRecorder recorder(&record, W, H);

    recorder.save();
        recorder.clipRect(SkRect::MakeWH(200, 200));
    recorder.restore();

    SkRecordNoopSaveRestores(&record);
    for (int i = 0; i < 3; i++) {
        assert_type<SkRecords::NoOp>(r, record, i);
    }
}

DEF_TEST(RecordOpts_NoopSaveRestores, r) {
    SkRecord record;
    SkRecorder recorder(&record, W, H);

    // The second pass will clean up this pair after the first pass noops all the innards.
    recorder.save();
        // A simple pointless pair of save/restore.
        recorder.save();
        recorder.restore();

        // As long as we don't draw in there, everything is a noop.
        recorder.save();
            recorder.clipRect(SkRect::MakeWH(200, 200));
            recorder.clipRect(SkRect::MakeWH(100, 100));
        recorder.restore();
    recorder.restore();

    SkRecordNoopSaveRestores(&record);
    for (int index = 0; index < record.count(); index++) {
        assert_type<SkRecords::NoOp>(r, record, index);
    }
}

DEF_TEST(RecordOpts_SaveSaveLayerRestoreRestore, r) {
    SkRecord record;
    SkRecorder recorder(&record, W, H);

    // A previous bug NoOp'd away the first 3 commands.
    recorder.save();
        recorder.saveLayer(nullptr, nullptr);
        recorder.restore();
    recorder.restore();

    SkRecordNoopSaveRestores(&record);
    switch (record.count()) {
        case 4:
            assert_type<SkRecords::Save>     (r, record, 0);
            assert_type<SkRecords::SaveLayer>(r, record, 1);
            assert_type<SkRecords::Restore>  (r, record, 2);
            assert_type<SkRecords::Restore>  (r, record, 3);
            break;
        case 2:
            assert_type<SkRecords::SaveLayer>(r, record, 0);
            assert_type<SkRecords::Restore>  (r, record, 1);
            break;
        case 0:
            break;
        default:
            REPORTER_ASSERT(r, false);
    }
}

#ifndef SK_BUILD_FOR_ANDROID_FRAMEWORK
static void assert_savelayer_restore(skiatest::Reporter* r,
                                     SkRecord* record,
                                     int i,
                                     bool shouldBeNoOped) {
    SkRecordNoopSaveLayerDrawRestores(record);
    if (shouldBeNoOped) {
        assert_type<SkRecords::NoOp>(r, *record, i);
        assert_type<SkRecords::NoOp>(r, *record, i+1);
    } else {
        assert_type<SkRecords::SaveLayer>(r, *record, i);
        assert_type<SkRecords::Restore>(r, *record, i+1);
    }
}

static void assert_savelayer_draw_restore(skiatest::Reporter* r,
                                          SkRecord* record,
                                          int i,
                                          bool shouldBeNoOped) {
    SkRecordNoopSaveLayerDrawRestores(record);
    if (shouldBeNoOped) {
        assert_type<SkRecords::NoOp>(r, *record, i);
        assert_type<SkRecords::NoOp>(r, *record, i+2);
    } else {
        assert_type<SkRecords::SaveLayer>(r, *record, i);
        assert_type<SkRecords::Restore>(r, *record, i+2);
    }
}

DEF_TEST(RecordOpts_NoopSaveLayerDrawRestore, r) {
    SkRecord record;
    SkRecorder recorder(&record, W, H);

    SkRect bounds = SkRect::MakeWH(100, 200);
    SkRect   draw = SkRect::MakeWH(50, 60);

    SkPaint alphaOnlyLayerPaint, translucentLayerPaint, xfermodeLayerPaint;
    alphaOnlyLayerPaint.setColor(0x03000000);  // Only alpha.
    translucentLayerPaint.setColor(0x03040506);  // Not only alpha.
    xfermodeLayerPaint.setBlendMode(SkBlendMode::kDstIn);  // Any effect will do.

    SkPaint opaqueDrawPaint, translucentDrawPaint;
    opaqueDrawPaint.setColor(0xFF020202);  // Opaque.
    translucentDrawPaint.setColor(0x0F020202);  // Not opaque.

    // SaveLayer/Restore removed: No paint = no point.
    recorder.saveLayer(nullptr, nullptr);
        recorder.drawRect(draw, opaqueDrawPaint);
    recorder.restore();
    assert_savelayer_draw_restore(r, &record, 0, true);

    // Bounds don't matter.
    recorder.saveLayer(&bounds, nullptr);
        recorder.drawRect(draw, opaqueDrawPaint);
    recorder.restore();
    assert_savelayer_draw_restore(r, &record, 3, true);

    // TODO(mtklein): test case with null draw paint

    // No change: layer paint isn't alpha-only.
    recorder.saveLayer(nullptr, &translucentLayerPaint);
        recorder.drawRect(draw, opaqueDrawPaint);
    recorder.restore();
    assert_savelayer_draw_restore(r, &record, 6, false);

    // No change: layer paint has an effect.
    recorder.saveLayer(nullptr, &xfermodeLayerPaint);
        recorder.drawRect(draw, opaqueDrawPaint);
    recorder.restore();
    assert_savelayer_draw_restore(r, &record, 9, false);

    // SaveLayer/Restore removed: we can fold in the alpha!
    recorder.saveLayer(nullptr, &alphaOnlyLayerPaint);
        recorder.drawRect(draw, translucentDrawPaint);
    recorder.restore();
    assert_savelayer_draw_restore(r, &record, 12, true);

    // SaveLayer/Restore removed: we can fold in the alpha!
    recorder.saveLayer(nullptr, &alphaOnlyLayerPaint);
        recorder.drawRect(draw, opaqueDrawPaint);
    recorder.restore();
    assert_savelayer_draw_restore(r, &record, 15, true);

    const SkRecords::DrawRect* drawRect = assert_type<SkRecords::DrawRect>(r, record, 16);
    REPORTER_ASSERT(r, drawRect != nullptr);
    REPORTER_ASSERT(r, drawRect->paint.getColor() == 0x03020202);

    // saveLayer w/ backdrop should NOT go away
    sk_sp<SkImageFilter> filter(SkBlurImageFilter::Make(3, 3, nullptr));
    recorder.saveLayer({ nullptr, nullptr, filter.get(), nullptr, nullptr, 0});
        recorder.drawRect(draw, opaqueDrawPaint);
    recorder.restore();
    assert_savelayer_draw_restore(r, &record, 18, false);

    // saveLayer w/ clip mask should also NOT go away
    {
        sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(10, 10));
        recorder.saveLayer({ nullptr, nullptr, nullptr, surface->makeImageSnapshot().get(),
                             nullptr, 0});
            recorder.drawRect(draw, opaqueDrawPaint);
        recorder.restore();
        assert_savelayer_draw_restore(r, &record, 21, false);
    }
}
#endif

static void assert_merge_svg_opacity_and_filter_layers(skiatest::Reporter* r,
                                                       SkRecord* record,
                                                       int i,
                                                       bool shouldBeNoOped) {
    SkRecordMergeSvgOpacityAndFilterLayers(record);
    if (shouldBeNoOped) {
        assert_type<SkRecords::NoOp>(r, *record, i);
        assert_type<SkRecords::NoOp>(r, *record, i + 6);
    } else {
        assert_type<SkRecords::SaveLayer>(r, *record, i);
        assert_type<SkRecords::Restore>(r, *record, i + 6);
    }
}

DEF_TEST(RecordOpts_MergeSvgOpacityAndFilterLayers, r) {
    SkRecord record;
    SkRecorder recorder(&record, W, H);

    SkRect bounds = SkRect::MakeWH(SkIntToScalar(100), SkIntToScalar(200));
    SkRect clip = SkRect::MakeWH(SkIntToScalar(50), SkIntToScalar(60));

    SkPaint alphaOnlyLayerPaint;
    alphaOnlyLayerPaint.setColor(0x03000000);  // Only alpha.
    SkPaint translucentLayerPaint;
    translucentLayerPaint.setColor(0x03040506);  // Not only alpha.
    SkPaint xfermodePaint;
    xfermodePaint.setBlendMode(SkBlendMode::kDstIn);
    SkPaint colorFilterPaint;
    colorFilterPaint.setColorFilter(
        SkColorFilters::Blend(SK_ColorLTGRAY, SkBlendMode::kSrcIn));

    SkPaint opaqueFilterLayerPaint;
    opaqueFilterLayerPaint.setColor(0xFF020202);  // Opaque.
    SkPaint translucentFilterLayerPaint;
    translucentFilterLayerPaint.setColor(0x0F020202);  // Not opaque.
    sk_sp<SkPicture> shape;
    {
        SkPictureRecorder recorder;
        SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(100), SkIntToScalar(100));
        SkPaint shapePaint;
        shapePaint.setColor(SK_ColorWHITE);
        canvas->drawRect(SkRect::MakeWH(SkIntToScalar(50), SkIntToScalar(50)), shapePaint);
        shape = recorder.finishRecordingAsPicture();
    }
    translucentFilterLayerPaint.setImageFilter(SkPictureImageFilter::Make(shape));

    int index = 0;

    {
        sk_sp<SkImageFilter> filter(SkBlurImageFilter::Make(3, 3, nullptr));
        // first (null) should be optimized, 2nd should not
        SkImageFilter* filters[] = { nullptr, filter.get() };

        // Any combination of these should cause the pattern to be optimized.
        SkRect* firstBounds[] = { nullptr, &bounds };
        SkPaint* firstPaints[] = { nullptr, &alphaOnlyLayerPaint };
        SkRect* secondBounds[] = { nullptr, &bounds };
        SkPaint* secondPaints[] = { &opaqueFilterLayerPaint, &translucentFilterLayerPaint };

        for (auto outerF : filters) {
            bool outerNoOped = !outerF;
            for (auto innerF : filters) {
                for (size_t i = 0; i < SK_ARRAY_COUNT(firstBounds); ++ i) {
                    for (size_t j = 0; j < SK_ARRAY_COUNT(firstPaints); ++j) {
                        for (size_t k = 0; k < SK_ARRAY_COUNT(secondBounds); ++k) {
                            for (size_t m = 0; m < SK_ARRAY_COUNT(secondPaints); ++m) {
                                bool innerNoOped = !secondBounds[k] && !secondPaints[m] && !innerF;

                                recorder.saveLayer({firstBounds[i], firstPaints[j], outerF,
                                                    nullptr, nullptr, 0});
                                recorder.save();
                                recorder.clipRect(clip);
                                recorder.saveLayer({secondBounds[k], secondPaints[m], innerF,
                                                    nullptr, nullptr, 0});
                                recorder.restore();
                                recorder.restore();
                                recorder.restore();
                                assert_merge_svg_opacity_and_filter_layers(r, &record, index,
                                                                           outerNoOped);
                            #ifndef SK_BUILD_FOR_ANDROID_FRAMEWORK
                                assert_savelayer_restore(r, &record, index + 3, innerNoOped);
                            #endif
                                index += 7;
                            }
                        }
                    }
                }
            }
        }
    }

    // These should cause the pattern to stay unoptimized:
    struct {
        SkPaint* firstPaint;
        SkPaint* secondPaint;
    } noChangeTests[] = {
        // No change: nullptr filter layer paint not implemented.
        { &alphaOnlyLayerPaint, nullptr },
        // No change: layer paint is not alpha-only.
        { &translucentLayerPaint, &opaqueFilterLayerPaint },
        // No change: layer paint has an xfereffect.
        { &xfermodePaint, &opaqueFilterLayerPaint },
        // No change: filter layer paint has an xfereffect.
        { &alphaOnlyLayerPaint, &xfermodePaint },
        // No change: layer paint has a color filter.
        { &colorFilterPaint, &opaqueFilterLayerPaint },
        // No change: filter layer paint has a color filter (until the optimization accounts for
        // constant color draws that can filter the color).
        { &alphaOnlyLayerPaint, &colorFilterPaint }
    };

    for (size_t i = 0; i < SK_ARRAY_COUNT(noChangeTests); ++i) {
        recorder.saveLayer(nullptr, noChangeTests[i].firstPaint);
        recorder.save();
        recorder.clipRect(clip);
        recorder.saveLayer(nullptr, noChangeTests[i].secondPaint);
        recorder.restore();
        recorder.restore();
        recorder.restore();
        assert_merge_svg_opacity_and_filter_layers(r, &record, index, false);
        index += 7;
    }

    // Test the folded alpha value.
    recorder.saveLayer(nullptr, &alphaOnlyLayerPaint);
    recorder.save();
    recorder.clipRect(clip);
    recorder.saveLayer(nullptr, &opaqueFilterLayerPaint);
    recorder.restore();
    recorder.restore();
    recorder.restore();
    assert_merge_svg_opacity_and_filter_layers(r, &record, index, true);

    const SkRecords::SaveLayer* saveLayer = assert_type<SkRecords::SaveLayer>(r, record, index + 3);
    REPORTER_ASSERT(r, saveLayer != nullptr);
    REPORTER_ASSERT(r, saveLayer->paint->getColor() == 0x03020202);

    index += 7;

    // Test that currently we do not fold alphas for patterns without the clip. This is just not
    // implemented.
    recorder.saveLayer(nullptr, &alphaOnlyLayerPaint);
    recorder.saveLayer(nullptr, &opaqueFilterLayerPaint);
    recorder.restore();
    recorder.restore();
    SkRecordMergeSvgOpacityAndFilterLayers(&record);
    assert_type<SkRecords::SaveLayer>(r, record, index);
    assert_type<SkRecords::SaveLayer>(r, record, index + 1);
    assert_type<SkRecords::Restore>(r, record, index + 2);
    assert_type<SkRecords::Restore>(r, record, index + 3);
    index += 4;
}

static void do_draw(SkCanvas* canvas, SkColor color, bool doLayer) {
    canvas->drawColor(SK_ColorWHITE);

    SkPaint p;
    p.setColor(color);

    if (doLayer) {
        canvas->saveLayer(nullptr, nullptr);
        p.setBlendMode(SkBlendMode::kSrc);
        canvas->drawPaint(p);
        canvas->restore();
    } else {
        canvas->drawPaint(p);
    }
}

static bool is_equal(SkSurface* a, SkSurface* b) {
    const SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
    SkPMColor ca, cb;
    a->readPixels(info, &ca, sizeof(SkPMColor), 0, 0);
    b->readPixels(info, &cb, sizeof(SkPMColor), 0, 0);
    return ca == cb;
}

// Test drawing w/ and w/o a simple layer (no bounds or paint), so see that drawing ops
// that *should* draw the same in fact do.
//
// Perform this test twice : once directly, and once via a picture
//
static void do_savelayer_srcmode(skiatest::Reporter* r, SkColor color) {
    for (int doPicture = 0; doPicture <= 1; ++doPicture) {
        sk_sp<SkSurface> surf0 = SkSurface::MakeRasterN32Premul(10, 10);
        sk_sp<SkSurface> surf1 = SkSurface::MakeRasterN32Premul(10, 10);
        SkCanvas* c0 = surf0->getCanvas();
        SkCanvas* c1 = surf1->getCanvas();

        SkPictureRecorder rec0, rec1;
        if (doPicture) {
            c0 = rec0.beginRecording(10, 10);
            c1 = rec1.beginRecording(10, 10);
        }

        do_draw(c0, color, false);
        do_draw(c1, color, true);

        if (doPicture) {
            surf0->getCanvas()->drawPicture(rec0.finishRecordingAsPicture());
            surf1->getCanvas()->drawPicture(rec1.finishRecordingAsPicture());
        }

        // we replicate the assert so we can see which line is reported if there is a failure
        if (doPicture) {
            REPORTER_ASSERT(r, is_equal(surf0.get(), surf1.get()));
        } else {
            REPORTER_ASSERT(r, is_equal(surf0.get(), surf1.get()));
        }
    }
}

DEF_TEST(savelayer_srcmode_opaque, r) {
    do_savelayer_srcmode(r, SK_ColorRED);
}

DEF_TEST(savelayer_srcmode_alpha, r) {
    do_savelayer_srcmode(r, 0x80FF0000);
}

