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

#include "gm/gm.h"

#include "include/core/SkCanvas.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPathBuilder.h"

/**
 * Repro case for https://bugs.chromium.org/p/chromium/issues/detail?id=913223
 *
 * The original bug was filed against square caps, but here we also draw the labyrinth using round
 * and butt caps.
 *
 * Square and round caps expose over-coverage on overlaps when using coverage counting.
 *
 * Butt caps expose under-coverage on abutted strokes when using a 'max()' coverage function.
 */
static void draw_labyrinth(SkCanvas* canvas, SkPaint::Cap cap) {
    constexpr static bool kRows[11][12] = {
        {1,1,1,1,1,1,1,1,1,1,1,1},
        {0,1,0,1,0,1,0,0,0,0,1,1},
        {0,0,0,0,1,0,0,0,0,1,1,1},
        {1,0,1,0,0,0,0,1,0,0,0,0},
        {0,1,1,0,0,0,0,0,0,1,1,1},
        {1,0,0,1,0,0,0,0,1,1,1,0},
        {0,1,0,1,1,1,0,0,1,1,1,0},
        {1,0,1,0,1,1,1,1,0,1,1,1},
        {0,0,1,0,0,1,0,0,0,0,0,1},
        {0,1,1,1,0,0,1,1,1,1,0,0},
        {1,1,1,1,1,1,1,1,1,1,1,1},
    };

    constexpr static bool kCols[13][10] = {
        {1,1,1,1,0,1,1,1,1,1},
        {0,0,1,0,0,0,1,1,1,0},
        {0,1,1,0,1,1,1,0,0,1},
        {1,1,0,0,0,0,1,0,1,0},
        {0,0,1,0,1,0,0,0,0,1},
        {0,0,1,1,1,0,0,0,1,0},
        {0,1,0,1,1,1,0,0,0,0},
        {1,1,1,0,1,1,1,0,1,0},
        {1,1,0,1,1,0,0,0,1,0},
        {0,0,1,0,0,0,0,0,0,1},
        {0,0,1,1,0,0,0,0,1,0},
        {0,0,0,0,0,0,1,0,0,1},
        {1,1,1,1,1,1,0,1,1,1},
    };

    SkPathBuilder maze;
    for (size_t y = 0; y < std::size(kRows); ++y) {
        for (size_t x = 0; x < std::size(kRows[0]); ++x) {
            if (kRows[y][x]) {
                maze.moveTo(x, y);
                maze.lineTo(x+1, y);
            }
        }
    }
    for (size_t x = 0; x < std::size(kCols); ++x) {
        for (size_t y = 0; y < std::size(kCols[0]); ++y) {
            if (kCols[x][y]) {
                maze.moveTo(x, y);
                maze.lineTo(x, y+1);
            }
        }
    }

    SkPaint paint;
    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(.1f);
    paint.setColor(0xff406060);
    paint.setAntiAlias(true);
    paint.setStrokeCap(cap);

    canvas->translate(10.5, 10.5);
    canvas->scale(40, 40);
    canvas->drawPath(maze.detach(), paint);
}

constexpr static int kWidth = 500;
constexpr static int kHeight = 420;

DEF_SIMPLE_GM(labyrinth_square, canvas, kWidth, kHeight) {
    draw_labyrinth(canvas, SkPaint::kSquare_Cap);
}

DEF_SIMPLE_GM(labyrinth_round, canvas, kWidth, kHeight) {
    draw_labyrinth(canvas, SkPaint::kRound_Cap);
}

DEF_SIMPLE_GM(labyrinth_butt, canvas, kWidth, kHeight) {
    draw_labyrinth(canvas, SkPaint::kButt_Cap);
}
