| Index: gm/OverStroke.cpp
|
| diff --git a/gm/OverStroke.cpp b/gm/OverStroke.cpp
|
| index 0c5679786cfc742b912a7cccee91fe66ba0c4435..f7134cd26ce617cd1a2d651284dc36055f2645fc 100644
|
| --- a/gm/OverStroke.cpp
|
| +++ b/gm/OverStroke.cpp
|
| @@ -13,6 +13,12 @@
|
| * overlap and create holes. There is not a really great algorithm for this
|
| * and several other 2D graphics engines have the same bug.
|
| *
|
| + * If we run this using Nvidia Path Renderer with:
|
| + * `path/to/dm --match OverStroke -w gm_out --gpu --config nvpr16`
|
| + * then we get correct results, so that is a possible direction of attack -
|
| + * use the GPU and a completely different algorithm to get correctness in
|
| + * Skia.
|
| + *
|
| * See crbug.com/589769 skbug.com/5405 skbug.com/5406
|
| */
|
|
|
| @@ -20,14 +26,28 @@
|
| #include "gm.h"
|
| #include "SkPaint.h"
|
| #include "SkPath.h"
|
| +#include "SkPathMeasure.h"
|
| +
|
| +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(500);
|
| + p.setStrokeWidth(OVERSTROKE_WIDTH);
|
|
|
| return p;
|
| }
|
| @@ -38,6 +58,7 @@ SkPath quad_path() {
|
| path.lineTo(100, 0);
|
| path.quadTo(50, -40,
|
| 0, 0);
|
| + path.close();
|
|
|
| return path;
|
| }
|
| @@ -62,19 +83,50 @@ SkPath oval_path() {
|
| return path;
|
| }
|
|
|
| +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);
|
| + tan.rotateCCW();
|
| +
|
| + 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;
|
| - p.setAntiAlias(true);
|
| - p.setStyle(SkPaint::kStroke_Style);
|
| - p.setStrokeWidth(3);
|
| + // canvas->scale(8, 8);
|
|
|
| + SkPaint p = make_normal_paint();
|
| SkPath path = quad_path();
|
|
|
| + draw_ribs(canvas, path);
|
| canvas->drawPath(path, p);
|
| }
|
|
|
| @@ -83,15 +135,14 @@ void draw_large_quad(SkCanvas *canvas) {
|
| 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;
|
| - fillp.setAntiAlias(true);
|
| - fillp.setStyle(SkPaint::kStroke_Style);
|
| + SkPaint fillp = make_normal_paint();
|
| fillp.setColor(SK_ColorMAGENTA);
|
|
|
| SkPath fillpath;
|
| @@ -101,7 +152,7 @@ void draw_quad_fillpath(SkCanvas *canvas) {
|
| }
|
|
|
| void draw_stroked_quad(SkCanvas *canvas) {
|
| - canvas->translate(200, 0);
|
| + canvas->translate(400, 0);
|
| draw_large_quad(canvas);
|
| draw_quad_fillpath(canvas);
|
| }
|
| @@ -109,16 +160,10 @@ void draw_stroked_quad(SkCanvas *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);
|
| -
|
| + SkPaint p = make_normal_paint();
|
| SkPath path = cubic_path();
|
|
|
| + draw_ribs(canvas, path);
|
| canvas->drawPath(path, p);
|
| }
|
|
|
| @@ -127,15 +172,14 @@ void draw_large_cubic(SkCanvas *canvas) {
|
| 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;
|
| - fillp.setAntiAlias(true);
|
| - fillp.setStyle(SkPaint::kStroke_Style);
|
| + SkPaint fillp = make_normal_paint();
|
| fillp.setColor(SK_ColorMAGENTA);
|
|
|
| SkPath fillpath;
|
| @@ -153,16 +197,11 @@ void draw_stroked_cubic(SkCanvas *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);
|
| + SkPaint p = make_normal_paint();
|
|
|
| SkPath path = oval_path();
|
|
|
| + draw_ribs(canvas, path);
|
| canvas->drawPath(path, p);
|
| }
|
|
|
| @@ -171,15 +210,14 @@ void draw_large_oval(SkCanvas *canvas) {
|
| 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;
|
| - fillp.setAntiAlias(true);
|
| - fillp.setStyle(SkPaint::kStroke_Style);
|
| + SkPaint fillp = make_normal_paint();
|
| fillp.setColor(SK_ColorMAGENTA);
|
|
|
| SkPath fillpath;
|
| @@ -210,9 +248,9 @@ DEF_SIMPLE_GM(OverStroke, canvas, 500, 500) {
|
| 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);
|
| + canvas->translate(150.0f * x, 150.0f * y);
|
| + canvas->scale(0.2f, 0.2f);
|
| + canvas->translate(300.0f, 400.0f);
|
|
|
| examples[i](canvas);
|
|
|
|
|