blob: 0c5679786cfc742b912a7cccee91fe66ba0c4435 [file] [log] [blame]
/*
* 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.
*
* See crbug.com/589769 skbug.com/5405 skbug.com/5406
*/
#include "gm.h"
#include "SkPaint.h"
#include "SkPath.h"
//////// path and paint builders
SkPaint make_overstroke_paint() {
SkPaint p;
p.setAntiAlias(true);
p.setStyle(SkPaint::kStroke_Style);
p.setStrokeWidth(500);
return p;
}
SkPath quad_path() {
SkPath path;
path.moveTo(0, 0);
path.lineTo(100, 0);
path.quadTo(50, -40,
0, 0);
return path;
}
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);
SkPath path;
path.arcTo(oval, 0, 359, true);
path.close();
return path;
}
///////// quads
void draw_small_quad(SkCanvas *canvas) {
// scaled so it's visible
canvas->scale(8, 8);
SkPaint p;
p.setAntiAlias(true);
p.setStyle(SkPaint::kStroke_Style);
p.setStrokeWidth(3);
SkPath path = quad_path();
canvas->drawPath(path, p);
}
void draw_large_quad(SkCanvas *canvas) {
SkPaint p = make_overstroke_paint();
SkPath path = quad_path();
canvas->drawPath(path, p);
}
void draw_quad_fillpath(SkCanvas *canvas) {
SkPath path = quad_path();
SkPaint p = make_overstroke_paint();
SkPaint fillp;
fillp.setAntiAlias(true);
fillp.setStyle(SkPaint::kStroke_Style);
fillp.setColor(SK_ColorMAGENTA);
SkPath fillpath;
p.getFillPath(path, &fillpath);
canvas->drawPath(fillpath, fillp);
}
void draw_stroked_quad(SkCanvas *canvas) {
canvas->translate(200, 0);
draw_large_quad(canvas);
draw_quad_fillpath(canvas);
}
////////// cubics
void draw_small_cubic(SkCanvas *canvas) {
// scaled so it's visible
canvas->scale(8, 8);
SkPaint p;
p.setAntiAlias(true);
p.setStyle(SkPaint::kStroke_Style);
p.setStrokeWidth(3);
SkPath path = cubic_path();
canvas->drawPath(path, p);
}
void draw_large_cubic(SkCanvas *canvas) {
SkPaint p = make_overstroke_paint();
SkPath path = cubic_path();
canvas->drawPath(path, p);
}
void draw_cubic_fillpath(SkCanvas *canvas) {
SkPath path = cubic_path();
SkPaint p = make_overstroke_paint();
SkPaint fillp;
fillp.setAntiAlias(true);
fillp.setStyle(SkPaint::kStroke_Style);
fillp.setColor(SK_ColorMAGENTA);
SkPath fillpath;
p.getFillPath(path, &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) {
// scaled so it's visible
canvas->scale(8, 8);
SkPaint p;
p.setAntiAlias(true);
p.setStyle(SkPaint::kStroke_Style);
p.setStrokeWidth(3);
SkPath path = oval_path();
canvas->drawPath(path, p);
}
void draw_large_oval(SkCanvas *canvas) {
SkPaint p = make_overstroke_paint();
SkPath path = oval_path();
canvas->drawPath(path, p);
}
void draw_oval_fillpath(SkCanvas *canvas) {
SkPath path = oval_path();
SkPaint p = make_overstroke_paint();
SkPaint fillp;
fillp.setAntiAlias(true);
fillp.setStyle(SkPaint::kStroke_Style);
fillp.setColor(SK_ColorMAGENTA);
SkPath fillpath;
p.getFillPath(path, &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(200.0f * x, 150.0f * y);
canvas->scale(0.25f, 0.25f);
canvas->translate(100.0f, 400.0f);
examples[i](canvas);
canvas->restore();
}
}