skia2/gm/thinconcavepaths.cpp
Stephen White 77169c8fd6 GrTessellator: fix for overlapping outer boundary edges in AA case.
When inflating outer path boundaries for edge AA, two outer boundary
edges may be collinear. In this case, they form part of the overlap
region, but they must not be removed on collapse, since they form
part of the outer boundary of the shape.

Bug: 846655
Change-Id: I4808b570cc4f82d6202862f7a8ecf0f8add771ef
Reviewed-on: https://skia-review.googlesource.com/132084
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Stephen White <senorblanco@chromium.org>
2018-06-05 13:58:59 +00:00

207 lines
6.4 KiB
C++

/*
* Copyright 2017 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"
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;
path.moveTo(10 + width, 10 + width);
path.lineTo(40, 10 + width);
path.lineTo(40, 20);
path.lineTo(10 + width, 20);
path.moveTo(10, 10);
path.lineTo(10, 20 + width);
path.lineTo(40 + width, 20 + width);
path.lineTo(40 + width, 10);
canvas->drawPath(path, paint);
}
void draw_thin_right_angle(SkCanvas* canvas, const SkPaint& paint, SkScalar width) {
SkPath path;
path.moveTo(10 + width, 10 + width);
path.lineTo(40, 10 + width);
path.lineTo(40, 20);
path.lineTo(40 + width, 20 + width);
path.lineTo(40 + width, 10);
path.lineTo(10, 10);
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;
path.moveTo(20, 10);
path.lineTo(80, 10);
path.lineTo(80, 10 + width);
path.lineTo(30, 10 + width);
path.lineTo(30, 20);
path.lineTo(20, 20);
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;
path.moveTo(30, 5);
path.lineTo(40 - offset, 15 - offset);
path.lineTo(60 + offset, 15 - offset);
path.lineTo(70, 5);
path.lineTo(70, 25);
path.lineTo(60 + offset, 15 + offset);
path.lineTo(40 - offset, 15 + offset);
path.lineTo(30, 25);
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;
path.moveTo(30, 5);
path.lineTo(30 + width, 5);
path.lineTo(30 + width, 25);
path.lineTo(30, 25);
path.moveTo(40, 5);
path.lineTo(40 + width, 5);
path.lineTo(40, 25);
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;
path.moveTo(10, 10);
path.lineTo(10, 20);
path.lineTo(50, 10 + width);
path.lineTo(90, 20);
path.lineTo(90, 10);
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;
path.moveTo(20 + width, 10);
path.lineTo(20 + width, 20);
path.lineTo(10 + width, 30);
path.lineTo(10 + width, 40);
path.lineTo(10 - width, 40);
path.lineTo(10 - width, 30);
path.lineTo(20 - width, 20);
path.lineTo(20 - width, 10);
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;
path.moveTo(20, 10);
path.lineTo(80, 10 + width * 0.5);
path.lineTo(30, 10 + width);
path.lineTo(30, 20);
path.lineTo(20, 20);
canvas->drawPath(path, paint);
}
void draw_small_i(SkCanvas* canvas, const SkPaint& paint, SkScalar width) {
SkPath path;
path.moveTo(1.25 - width, 18.75 + width);
path.lineTo(1.25 - width, 12.25 - width);
path.lineTo(2.50 + width, 12.25 - width);
path.lineTo(2.50 + width, 18.75 + width);
path.moveTo(1.25 - width, 11.75 + width);
path.lineTo(1.25 - width, 10.25 - width);
path.lineTo(2.50 + width, 10.25 - width);
path.lineTo(2.50 + width, 11.75 + width);
canvas->drawPath(path, paint);
}
};
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);
}