/*
 * 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);

    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));
        }
    }
}

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);
}
