/*
 * Copyright 2017 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/SkPath.h"
#include "include/core/SkPathBuilder.h"
#include "include/core/SkScalar.h"

namespace {
// Test thin stroked rect (stroked "by hand", not by stroking).
void draw_thin_stroked_rect(SkCanvas* canvas, const SkPaint& paint, SkScalar width) {
    SkPath path = SkPathBuilder()
                  .moveTo(10 + width, 10 + width)
                  .lineTo(40,         10 + width)
                  .lineTo(40,         20)
                  .lineTo(10 + width, 20)
                  .moveTo(10,         10)
                  .lineTo(10,         20 + width)
                  .lineTo(40 + width, 20 + width)
                  .lineTo(40 + width, 10)
                  .detach();
    canvas->drawPath(path, paint);
}

void draw_thin_right_angle(SkCanvas* canvas, const SkPaint& paint, SkScalar width) {
    SkPath path = SkPathBuilder()
                  .moveTo(10 + width, 10 + width)
                  .lineTo(40,         10 + width)
                  .lineTo(40,         20)
                  .lineTo(40 + width, 20 + width)
                  .lineTo(40 + width, 10)
                  .lineTo(10,         10)
                  .detach();
    canvas->drawPath(path, paint);
}

// Test thin horizontal line (<1 pixel) which should give lower alpha.
void draw_golf_club(SkCanvas* canvas, const SkPaint& paint, SkScalar width) {
    SkPath path = SkPathBuilder()
                  .moveTo(20, 10)
                  .lineTo(80, 10)
                  .lineTo(80, 10 + width)
                  .lineTo(30, 10 + width)
                  .lineTo(30, 20)
                  .lineTo(20, 20)
                  .detach();
    canvas->drawPath(path, paint);
}

// Test thin lines between two filled regions. The outer edges overlap, but
// there are no inverted edges to fix.
void draw_barbell(SkCanvas* canvas, const SkPaint& paint, SkScalar width) {
    SkScalar offset = width * 0.5f;
    SkPath path = SkPathBuilder()
                  .moveTo(30,  5)
                  .lineTo(40 - offset, 15 - offset)
                  .lineTo(60 + offset, 15 - offset)
                  .lineTo(70,  5)
                  .lineTo(70, 25)
                  .lineTo(60 + offset, 15 + offset)
                  .lineTo(40 - offset, 15 + offset)
                  .lineTo(30, 25)
                  .detach();
    canvas->drawPath(path, paint);
}

// Test a thin rectangle and triangle. The top and bottom inner edges of the
// rectangle and all inner edges of the triangle invert on stroking.
void draw_thin_rect_and_triangle(SkCanvas* canvas, const SkPaint& paint, SkScalar width) {
    SkPath path = SkPathBuilder()
                  .moveTo(30,  5)
                  .lineTo(30 + width,  5)
                  .lineTo(30 + width,  25)
                  .lineTo(30,  25)
                  .moveTo(40,  5)
                  .lineTo(40 + width,  5)
                  .lineTo(40,  25)
                  .detach();
    canvas->drawPath(path, paint);
}

// Two triangles joined by a very thin bridge. The tiny triangle formed
// by the inner edges at the bridge is inverted.
// (These are actually now more phat pants than hipster pants.)
void draw_hipster_pants(SkCanvas* canvas, const SkPaint& paint, SkScalar width) {
    SkPath path = SkPathBuilder()
                  .moveTo(10, 10)
                  .lineTo(10, 20)
                  .lineTo(50, 10 + width)
                  .lineTo(90, 20)
                  .lineTo(90, 10)
                  .detach();
    canvas->drawPath(path, paint);
}

// A thin z-shape whose interior inverts on stroking. The top and bottom inner edges invert, and
// the connector edges at the "elbows" intersect the inner edges.
void draw_skinny_snake(SkCanvas* canvas, const SkPaint& paint, SkScalar width) {
    SkPath path = SkPathBuilder()
                  .moveTo(20 + width, 10)
                  .lineTo(20 + width, 20)
                  .lineTo(10 + width, 30)
                  .lineTo(10 + width, 40)
                  .lineTo(10 - width, 40)
                  .lineTo(10 - width, 30)
                  .lineTo(20 - width, 20)
                  .lineTo(20 - width, 10)
                  .detach();
    canvas->drawPath(path, paint);
}

// Test pointy features whose outer edges extend far to the right on stroking.
void draw_pointy_golf_club(SkCanvas* canvas, const SkPaint& paint, SkScalar width) {
    SkPath path = SkPathBuilder()
                  .moveTo(20, 10)
                  .lineTo(80, 10 + width * 0.5)
                  .lineTo(30, 10 + width)
                  .lineTo(30, 20)
                  .lineTo(20, 20)
                  .detach();
    canvas->drawPath(path, paint);
}

void draw_small_i(SkCanvas* canvas, const SkPaint& paint, SkScalar width) {
    SkPath path = SkPathBuilder()
                  .moveTo(1.25 - width, 18.75 + width)
                  .lineTo(1.25 - width, 12.25 - width)
                  .lineTo(2.50 + width, 12.25 - width)
                  .lineTo(2.50 + width, 18.75 + width)
                  .moveTo(1.25 - width, 11.75 + width)
                  .lineTo(1.25 - width, 10.25 - width)
                  .lineTo(2.50 + width, 10.25 - width)
                  .lineTo(2.50 + width, 11.75 + width)
                  .detach();
    canvas->drawPath(path, paint);
}



}  // namespace

DEF_SIMPLE_GM(thinconcavepaths, canvas, 550, 400) {
    SkPaint paint;

    paint.setAntiAlias(true);
    paint.setStyle(SkPaint::kFill_Style);

    canvas->save();
    for (SkScalar width = 0.5f; width < 2.05f; width += 0.25f) {
        draw_thin_stroked_rect(canvas, paint, width);
        canvas->translate(0, 25);
    }
    canvas->restore();
    canvas->translate(50, 0);
    canvas->save();
    for (SkScalar width = 0.5f; width < 2.05f; width += 0.25f) {
        draw_thin_right_angle(canvas, paint, width);
        canvas->translate(0, 25);
    }
    canvas->restore();
    canvas->translate(40, 0);
    canvas->save();
    for (SkScalar width = 0.2f; width < 2.1f; width += 0.2f) {
        draw_golf_club(canvas, paint, width);
        canvas->translate(0, 30);
    }
    canvas->restore();
    canvas->translate(70, 0);
    canvas->save();
    for (SkScalar width = 0.2f; width < 2.1f; width += 0.2f) {
        draw_thin_rect_and_triangle(canvas, paint, width);
        canvas->translate(0, 30);
    }
    canvas->restore();
    canvas->translate(30, 0);
    canvas->save();

    for (SkScalar width = 0.2f; width < 2.1f; width += 0.2f) {
        draw_barbell(canvas, paint, width);
        canvas->translate(0, 30);
    }
    canvas->restore();
    canvas->translate(80, 0);
    canvas->save();
    for (SkScalar width = 0.2f; width < 2.1f; width += 0.2f) {
        draw_hipster_pants(canvas, paint, width);
        canvas->translate(0, 30);
    }
    canvas->restore();
    canvas->translate(100, 0);
    canvas->save();
    for (SkScalar width = 0.2f; width < 2.1f; width += 0.2f) {
        draw_skinny_snake(canvas, paint, width);
        canvas->translate(0, 30);
    }
    canvas->restore();
    canvas->translate(30, 0);
    canvas->save();
    for (SkScalar width = 0.2f; width < 2.1f; width += 0.2f) {
        draw_pointy_golf_club(canvas, paint, width);
        canvas->translate(0, 30);
    }
    canvas->restore();
    canvas->translate(100, 0);
    canvas->save();
    for (SkScalar width = 0.0f; width < 0.5f; width += 0.05f) {
        draw_small_i(canvas, paint, width);
        canvas->translate(0, 30);
    }
    canvas->restore();
    canvas->translate(100, 0);
}
