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

#include "SkCanvas.h"
#include "SkHighContrastFilter.h"
#include "Test.h"

DEF_TEST(HighContrastFilter_FilterImage, reporter) {
    SkHighContrastConfig config;
    config.fInvertStyle = SkHighContrastConfig::InvertStyle::kInvertLightness;

    int w = 10, h = 10;
    SkBitmap filterResult, paintResult;

    filterResult.allocN32Pixels(w, h);
    SkCanvas canvasFilter(filterResult);
    canvasFilter.clear(0x00000000);

    paintResult.allocN32Pixels(w, h);
    SkCanvas canvasPaint(paintResult);
    canvasPaint.clear(0x00000000);

    SkPaint paint;
    paint.setColor(SK_ColorBLUE);
    SkRect r = SkRect::MakeLTRB(SkIntToScalar(2), SkIntToScalar(2),
                                SkIntToScalar(8), SkIntToScalar(8));
    canvasPaint.drawRect(r, paint);

    paint.setColorFilter(SkHighContrastFilter::Make(config));
    canvasFilter.drawRect(r, paint);

    paintResult.lockPixels();
    filterResult.lockPixels();
    for (int y = r.top(); y < r.bottom(); ++y) {
        for (int x = r.left(); x < r.right(); ++x) {
            SkColor paintColor = paintResult.getColor(x, y);
            SkColor filterColor = filterResult.getColor(x, y);
            REPORTER_ASSERT(
                reporter, filterColor ==
                paint.getColorFilter()->filterColor(paintColor));
        }
    }
    paintResult.unlockPixels();
    filterResult.unlockPixels();
}

DEF_TEST(HighContrastFilter_SanityCheck, reporter) {
    SkHighContrastConfig config;
    config.fInvertStyle = SkHighContrastConfig::InvertStyle::kInvertLightness;
    sk_sp<SkColorFilter> filter = SkHighContrastFilter::Make(config);

    SkColor white_inverted = filter->filterColor(SK_ColorWHITE);
    REPORTER_ASSERT(reporter, white_inverted == SK_ColorBLACK);

    SkColor black_inverted = filter->filterColor(SK_ColorBLACK);
    REPORTER_ASSERT(reporter, black_inverted == SK_ColorWHITE);
}

DEF_TEST(HighContrastFilter_InvalidInputs, reporter) {
    SkHighContrastConfig config;
    REPORTER_ASSERT(reporter, config.isValid());

    // Valid invert style
    config.fInvertStyle = SkHighContrastConfig::InvertStyle::kInvertBrightness;
    REPORTER_ASSERT(reporter, config.isValid());
    config.fInvertStyle = SkHighContrastConfig::InvertStyle::kInvertLightness;
    REPORTER_ASSERT(reporter, config.isValid());
    sk_sp<SkColorFilter> filter = SkHighContrastFilter::Make(config);
    REPORTER_ASSERT(reporter, filter);

    // Invalid invert style
    config.fInvertStyle = static_cast<SkHighContrastConfig::InvertStyle>(999);
    REPORTER_ASSERT(reporter, !config.isValid());
    filter = SkHighContrastFilter::Make(config);
    REPORTER_ASSERT(reporter, !filter);

    // Valid contrast
    config.fInvertStyle = SkHighContrastConfig::InvertStyle::kInvertBrightness;
    config.fContrast = 0.5f;
    REPORTER_ASSERT(reporter, config.isValid());
    filter = SkHighContrastFilter::Make(config);
    REPORTER_ASSERT(reporter, filter);

    // Invalid contrast
    config.fContrast = 1.1f;
    REPORTER_ASSERT(reporter, !config.isValid());
    filter = SkHighContrastFilter::Make(config);
    REPORTER_ASSERT(reporter, !filter);
}
