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


/*
 * This GM exercises stroking of paths with large stroke lengths, which is
 * referred to as "overstroke" for brevity. In Skia as of 8/2016 we offset
 * each part of the curve the request amount even if it makes the offsets
 * overlap and create holes. There is not a really great algorithm for this
 * and several other 2D graphics engines have the same bug.
 *
 * The old Nvidia Path Renderer used to yield correct results, so a possible
 * direction of attack is to use the GPU and a completely different algorithm.
 *
 * See crbug.com/589769 skbug.com/5405 skbug.com/5406
 */

#include "gm/gm.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPathBuilder.h"
#include "include/core/SkPathMeasure.h"
#include "include/core/SkPathUtils.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkScalar.h"
#include "src/core/SkPointPriv.h"

#include <cstddef>

const SkScalar OVERSTROKE_WIDTH = 500.0f;
const SkScalar NORMALSTROKE_WIDTH = 3.0f;

//////// path and paint builders

SkPaint make_normal_paint() {
    SkPaint p;
    p.setAntiAlias(true);
    p.setStyle(SkPaint::kStroke_Style);
    p.setStrokeWidth(NORMALSTROKE_WIDTH);
    p.setColor(SK_ColorBLUE);

    return p;
}

SkPaint make_overstroke_paint() {
    SkPaint p;
    p.setAntiAlias(true);
    p.setStyle(SkPaint::kStroke_Style);
    p.setStrokeWidth(OVERSTROKE_WIDTH);

    return p;
}

SkPath quad_path() {
    return SkPathBuilder().moveTo(0, 0)
                          .lineTo(100, 0)
                          .quadTo(50, -40, 0, 0)
                          .close()
                          .detach();
}

SkPath cubic_path() {
    SkPath path;
    path.moveTo(0, 0);
    path.cubicTo(25, 75,
                 75, -50,
                 100, 0);

    return path;
}

SkPath oval_path() {
    SkRect oval = SkRect::MakeXYWH(0, -25, 100, 50);

    return SkPathBuilder().arcTo(oval, 0, 359, true).close().detach();
}

SkPath ribs_path(SkPath path, SkScalar radius) {
    SkPath ribs;

    const SkScalar spacing = 5.0f;
    float accum = 0.0f;

    SkPathMeasure meas(path, false);
    SkScalar length = meas.getLength();
    SkPoint pos;
    SkVector tan;
    while (accum < length) {
        if (meas.getPosTan(accum, &pos, &tan)) {
            tan.scale(radius);
            SkPointPriv::RotateCCW(&tan);

            ribs.moveTo(pos.x() + tan.x(), pos.y() + tan.y());
            ribs.lineTo(pos.x() - tan.x(), pos.y() - tan.y());
        }
        accum += spacing;
    }

    return ribs;
}

void draw_ribs(SkCanvas *canvas, SkPath path) {
    SkPath ribs = ribs_path(path, OVERSTROKE_WIDTH/2.0f);
    SkPaint p = make_normal_paint();
    p.setStrokeWidth(1);
    p.setColor(SK_ColorBLUE);
    p.setColor(SK_ColorGREEN);

    canvas->drawPath(ribs, p);
}

///////// quads

void draw_small_quad(SkCanvas *canvas) {
    // scaled so it's visible
    // canvas->scale(8, 8);

    SkPaint p = make_normal_paint();
    SkPath path = quad_path();

    draw_ribs(canvas, path);
    canvas->drawPath(path, p);
}

void draw_large_quad(SkCanvas *canvas) {
    SkPaint p = make_overstroke_paint();
    SkPath path = quad_path();

    canvas->drawPath(path, p);
    draw_ribs(canvas, path);
}

void draw_quad_fillpath(SkCanvas *canvas) {
    SkPath path = quad_path();
    SkPaint p = make_overstroke_paint();

    SkPaint fillp = make_normal_paint();
    fillp.setColor(SK_ColorMAGENTA);

    SkPath fillpath;
    skpathutils::FillPathWithPaint(path, p, &fillpath);

    canvas->drawPath(fillpath, fillp);
}

void draw_stroked_quad(SkCanvas *canvas) {
    canvas->translate(400, 0);
    draw_large_quad(canvas);
    draw_quad_fillpath(canvas);
}

////////// cubics

void draw_small_cubic(SkCanvas *canvas) {
    SkPaint p = make_normal_paint();
    SkPath path = cubic_path();

    draw_ribs(canvas, path);
    canvas->drawPath(path, p);
}

void draw_large_cubic(SkCanvas *canvas) {
    SkPaint p = make_overstroke_paint();
    SkPath path = cubic_path();

    canvas->drawPath(path, p);
    draw_ribs(canvas, path);
}

void draw_cubic_fillpath(SkCanvas *canvas) {
    SkPath path = cubic_path();
    SkPaint p = make_overstroke_paint();

    SkPaint fillp = make_normal_paint();
    fillp.setColor(SK_ColorMAGENTA);

    SkPath fillpath;
    skpathutils::FillPathWithPaint(path, p, &fillpath);

    canvas->drawPath(fillpath, fillp);
}

void draw_stroked_cubic(SkCanvas *canvas) {
    canvas->translate(400, 0);
    draw_large_cubic(canvas);
    draw_cubic_fillpath(canvas);
}

////////// ovals

void draw_small_oval(SkCanvas *canvas) {
    SkPaint p = make_normal_paint();

    SkPath path = oval_path();

    draw_ribs(canvas, path);
    canvas->drawPath(path, p);
}

void draw_large_oval(SkCanvas *canvas) {
    SkPaint p = make_overstroke_paint();
    SkPath path = oval_path();

    canvas->drawPath(path, p);
    draw_ribs(canvas, path);
}

void draw_oval_fillpath(SkCanvas *canvas) {
    SkPath path = oval_path();
    SkPaint p = make_overstroke_paint();

    SkPaint fillp = make_normal_paint();
    fillp.setColor(SK_ColorMAGENTA);

    SkPath fillpath;
    skpathutils::FillPathWithPaint(path, p, &fillpath);

    canvas->drawPath(fillpath, fillp);
}

void draw_stroked_oval(SkCanvas *canvas) {
    canvas->translate(400, 0);
    draw_large_oval(canvas);
    draw_oval_fillpath(canvas);
}

////////// gm

void (*examples[])(SkCanvas *canvas) = {
    draw_small_quad,    draw_stroked_quad, draw_small_cubic,
    draw_stroked_cubic, draw_small_oval,   draw_stroked_oval,
};

DEF_SIMPLE_GM(OverStroke, canvas, 500, 500) {
    const size_t length = sizeof(examples) / sizeof(examples[0]);
    const size_t width = 2;

    for (size_t i = 0; i < length; i++) {
        int x = (int)(i % width);
        int y = (int)(i / width);

        canvas->save();
        canvas->translate(150.0f * x, 150.0f * y);
        canvas->scale(0.2f, 0.2f);
        canvas->translate(300.0f, 400.0f);

        examples[i](canvas);

        canvas->restore();
    }
}
