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

#include "gm.h"
#include "SkCanvas.h"
#include "SkPath.h"

static SkPath generate_square(SkScalar cx, SkScalar cy, SkScalar w) {
    SkRect rect = SkRect::MakeXYWH(cx - w / 2, cy - w / 2, w, w);
    SkPath path;
    path.addRect(rect);
    return path;
}

static SkPath generate_rect_line(SkScalar cx, SkScalar cy, SkScalar l) {
    SkRect rect = SkRect::MakeXYWH(cx - l / 2, cy, l, 0);
    SkPath path;
    path.addRect(rect);
    return path;
}

static SkPath generate_circle(SkScalar cx, SkScalar cy, SkScalar d) {
    SkPath path;
    path.addCircle(cx, cy, d/2, SkPath::kCW_Direction);
    return path;
}

static SkPath generate_line(SkScalar cx, SkScalar cy, SkScalar l) {
    SkPath path;
    path.moveTo(cx - l / 2, cy);
    path.lineTo(cx + l / 2, cy);
    return path;
}

namespace {
SkPaint::Style styles[] = {
        SkPaint::kStroke_Style,
        SkPaint::kStrokeAndFill_Style,
        SkPaint::kFill_Style
};
SkScalar pathSizes[] = {
        40,
        10,
        0
};
SkScalar strokeWidths[] = {
        10,
        0
};
SkPath ((*paths[])(SkScalar, SkScalar, SkScalar)) = {
        generate_square,
        generate_rect_line,
        generate_circle,
        generate_line
};

const SkScalar slideWidth = 90, slideHeight = 90;
const SkScalar slideBoundary = 5;

}  // namespace

DEF_SIMPLE_GM(inverse_paths, canvas, 800, 900) {
        SkScalar cx = slideWidth / 2 + slideBoundary;
        SkScalar cy = slideHeight / 2 + slideBoundary;
        SkScalar dx = slideWidth + 2 * slideBoundary;
        SkScalar dy = slideHeight + 2 * slideBoundary;

        SkRect clipRect = SkRect::MakeLTRB(slideBoundary, slideBoundary,
                                           slideBoundary + slideWidth,
                                           slideBoundary + slideHeight);
        SkPaint clipPaint;
        clipPaint.setStyle(SkPaint::kStroke_Style);
        clipPaint.setStrokeWidth(SkIntToScalar(2));

        SkPaint outlinePaint;
        outlinePaint.setColor(0x40000000);
        outlinePaint.setStyle(SkPaint::kStroke_Style);
        outlinePaint.setStrokeWidth(SkIntToScalar(0));

        for (size_t styleIndex = 0; styleIndex < SK_ARRAY_COUNT(styles);
                styleIndex++) {
            for (size_t sizeIndex = 0; sizeIndex < SK_ARRAY_COUNT(pathSizes);
                    sizeIndex++) {
                SkScalar size = pathSizes[sizeIndex];

                canvas->save();

                for (size_t widthIndex = 0;
                        widthIndex < SK_ARRAY_COUNT(strokeWidths);
                        widthIndex++) {
                    SkPaint paint;
                    paint.setColor(0xff007000);
                    paint.setStrokeWidth(strokeWidths[widthIndex]);
                    paint.setStyle(styles[styleIndex]);

                    for (size_t pathIndex = 0;
                            pathIndex < SK_ARRAY_COUNT(paths);
                            pathIndex++) {
                        canvas->drawRect(clipRect, clipPaint);

                        canvas->save();
                        canvas->clipRect(clipRect);

                        SkPath path = paths[pathIndex](cx, cy, size);
                        path.setFillType(SkPath::kInverseWinding_FillType);
                        canvas->drawPath(path, paint);

                        path.setFillType(SkPath::kWinding_FillType);
                        canvas->drawPath(path, outlinePaint);

                        canvas->restore();
                        canvas->translate(dx, 0);
                    }
                }

                canvas->restore();
                canvas->translate(0, dy);
            }
        }
}
