Migrate to using SkPathBuilder

Change-Id: I86a75670d7b919313747175ca3e49ef7472061fd
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/310977
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Mike Reed <reed@google.com>
This commit is contained in:
Mike Reed 2020-08-16 11:15:41 -04:00 committed by Skia Commit-Bot
parent 6704bc87d2
commit 15a5403cd3
12 changed files with 248 additions and 280 deletions

View File

@ -9,129 +9,128 @@
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPath.h"
#include "include/core/SkPathBuilder.h"
#include "include/core/SkScalar.h"
#include "include/private/SkFloatBits.h"
#include "src/core/SkPathPriv.h"
#define W 800
#define H 800
DEF_SIMPLE_GM(analytic_antialias_convex, canvas, W, H) {
SkPaint p;
p.setColor(SK_ColorRED);
p.setAntiAlias(true);
SkPaint p;
p.setColor(SK_ColorRED);
p.setAntiAlias(true);
canvas->clear(0xFFFFFFFF);
canvas->clear(0xFFFFFFFF);
canvas->save();
canvas->save();
SkScalar y = 0;
SkScalar y = 0;
canvas->translate(0, y);
canvas->rotate(1);
canvas->drawRect({ 20, 20, 200, 200 }, p);
canvas->restore();
canvas->translate(0, y);
canvas->rotate(1);
canvas->drawRect({ 20, 20, 200, 200 }, p);
canvas->restore();
y += 200;
y += 200;
canvas->save();
canvas->translate(0, y);
canvas->rotate(1);
canvas->drawRect({ 20, 20, 20.2f, 200 }, p);
canvas->drawRect({ 20, 200, 200, 200.1f }, p);
canvas->drawCircle(100, 100, 30, p);
canvas->restore();
canvas->save();
canvas->translate(0, y);
canvas->rotate(1);
canvas->drawRect({ 20, 20, 20.2f, 200 }, p);
canvas->drawRect({ 20, 200, 200, 200.1f }, p);
canvas->drawCircle(100, 100, 30, p);
canvas->restore();
// The following path is empty but it'll reveal bug chrome:662914
SkPath path;
path.moveTo(SkBits2Float(0x429b9d5c), SkBits2Float(0x4367a041)); // 77.8073f, 231.626f
// 77.8075f, 231.626f, 77.8074f, 231.625f, 77.8073f, 231.625f
path.cubicTo(SkBits2Float(0x429b9d71), SkBits2Float(0x4367a022),
SkBits2Float(0x429b9d64), SkBits2Float(0x4367a009),
SkBits2Float(0x429b9d50), SkBits2Float(0x43679ff2));
path.lineTo(SkBits2Float(0x429b9d5c), SkBits2Float(0x4367a041)); // 77.8073f, 231.626f
path.close();
canvas->drawPath(path, p);
// The following path is empty but it'll reveal bug chrome:662914
SkPathBuilder path;
path.moveTo(SkBits2Float(0x429b9d5c), SkBits2Float(0x4367a041)); // 77.8073f, 231.626f
// 77.8075f, 231.626f, 77.8074f, 231.625f, 77.8073f, 231.625f
path.cubicTo(SkBits2Float(0x429b9d71), SkBits2Float(0x4367a022),
SkBits2Float(0x429b9d64), SkBits2Float(0x4367a009),
SkBits2Float(0x429b9d50), SkBits2Float(0x43679ff2));
path.lineTo(SkBits2Float(0x429b9d5c), SkBits2Float(0x4367a041)); // 77.8073f, 231.626f
path.close();
canvas->drawPath(path.detach(), p);
// The following path reveals a subtle SkAnalyticQuadraticEdge::updateQuadratic bug:
// we should not use any snapped y for the intermediate values whose error may accumulate;
// snapping should only be allowed once before updateLine.
path.reset();
path.moveTo(SkBits2Float(0x434ba71e), SkBits2Float(0x438a06d0)); // 203.653f, 276.053f
path.lineTo(SkBits2Float(0x43492a74), SkBits2Float(0x4396d70d)); // 201.166f, 301.68f
// 200.921f, 304.207f, 196.939f, 303.82f, 0.707107f
path.conicTo(SkBits2Float(0x4348ebaf), SkBits2Float(0x43981a75),
SkBits2Float(0x4344f079), SkBits2Float(0x4397e900), SkBits2Float(0x3f3504f3));
path.close();
// Manually setting convexity is required. Otherwise, this path will be considered concave.
path.setConvexityType(SkPathConvexityType::kConvex);
canvas->drawPath(path, p);
// The following path reveals a subtle SkAnalyticQuadraticEdge::updateQuadratic bug:
// we should not use any snapped y for the intermediate values whose error may accumulate;
// snapping should only be allowed once before updateLine.
path.moveTo(SkBits2Float(0x434ba71e), SkBits2Float(0x438a06d0)); // 203.653f, 276.053f
path.lineTo(SkBits2Float(0x43492a74), SkBits2Float(0x4396d70d)); // 201.166f, 301.68f
// 200.921f, 304.207f, 196.939f, 303.82f, 0.707107f
path.conicTo(SkBits2Float(0x4348ebaf), SkBits2Float(0x43981a75),
SkBits2Float(0x4344f079), SkBits2Float(0x4397e900), SkBits2Float(0x3f3504f3));
path.close();
// Manually setting convexity is required. Otherwise, this path will be considered concave.
SkPathPriv::SetConvexityType(&path, SkPathConvexityType::kConvex);
canvas->drawPath(path.detach(), p);
// skbug.com/7573
y += 200;
canvas->save();
canvas->translate(0, y);
p.setAntiAlias(true);
path.reset();
path.moveTo(1.98009784f, 9.0162744f);
path.lineTo(47.843992f, 10.1922744f);
path.lineTo(47.804008f, 11.7597256f);
path.lineTo(1.93990216f, 10.5837256f);
canvas->drawPath(path, p);
canvas->restore();
// skbug.com/7573
y += 200;
canvas->save();
canvas->translate(0, y);
p.setAntiAlias(true);
path.moveTo(1.98009784f, 9.0162744f);
path.lineTo(47.843992f, 10.1922744f);
path.lineTo(47.804008f, 11.7597256f);
path.lineTo(1.93990216f, 10.5837256f);
canvas->drawPath(path.detach(), p);
canvas->restore();
// skbug.com/7813
// t8888 splits the 800-high canvas into 3 pieces; the boundary is close to 266 and 534
path.reset();
path.moveTo(700, 266);
path.lineTo(710, 266);
path.lineTo(710, 534);
path.lineTo(700, 534);
canvas->drawPath(path, p);
// skbug.com/7813
// t8888 splits the 800-high canvas into 3 pieces; the boundary is close to 266 and 534
path.moveTo(700, 266);
path.lineTo(710, 266);
path.lineTo(710, 534);
path.lineTo(700, 534);
canvas->drawPath(path.detach(), p);
}
DEF_SIMPLE_GM(analytic_antialias_general, canvas, W, H) {
SkPaint p;
p.setColor(SK_ColorRED);
p.setAntiAlias(true);
SkPaint p;
p.setColor(SK_ColorRED);
p.setAntiAlias(true);
canvas->clear(0xFFFFFFFF);
canvas->clear(0xFFFFFFFF);
canvas->save();
canvas->rotate(1);
const SkScalar R = 115.2f, C = 128.0f;
SkPath path;
path.moveTo(C + R, C);
for (int i = 1; i < 8; ++i) {
SkScalar a = 2.6927937f * i;
path.lineTo(C + R * SkScalarCos(a), C + R * SkScalarSin(a));
}
canvas->drawPath(path, p);
canvas->restore();
canvas->save();
canvas->rotate(1);
const SkScalar R = 115.2f, C = 128.0f;
SkPathBuilder builder;
builder.moveTo(C + R, C);
for (int i = 1; i < 8; ++i) {
SkScalar a = 2.6927937f * i;
builder.lineTo(C + R * SkScalarCos(a), C + R * SkScalarSin(a));
}
SkPath path = builder.detach();
canvas->drawPath(path, p);
canvas->restore();
canvas->save();
canvas->translate(200, 0);
canvas->rotate(1);
p.setStyle(SkPaint::kStroke_Style);
p.setStrokeWidth(5);
canvas->drawPath(path, p);
canvas->restore();
canvas->save();
canvas->translate(200, 0);
canvas->rotate(1);
p.setStyle(SkPaint::kStroke_Style);
p.setStrokeWidth(5);
canvas->drawPath(path, p);
canvas->restore();
// The following two paths test if we correctly cumulates the alpha on the middle pixel
// column where the left rect and the right rect abut.
p.setStyle(SkPaint::kFill_Style);
canvas->translate(0, 300);
path.reset();
path.addRect({20, 20, 100.4999f, 100});
path.addRect({100.5001f, 20, 200, 100});
canvas->drawPath(path, p);
// The following two paths test if we correctly cumulates the alpha on the middle pixel
// column where the left rect and the right rect abut.
p.setStyle(SkPaint::kFill_Style);
canvas->translate(0, 300);
path.reset();
path.addRect({20, 20, 100.4999f, 100});
path.addRect({100.5001f, 20, 200, 100});
canvas->drawPath(path, p);
canvas->translate(300, 0);
path.reset();
path.addRect({20, 20, 100.1f, 100});
path.addRect({100.9f, 20, 200, 100});
canvas->drawPath(path, p);
canvas->translate(300, 0);
path.reset();
path.addRect({20, 20, 100.1f, 100});
path.addRect({100.9f, 20, 200, 100});
canvas->drawPath(path, p);
}
DEF_SIMPLE_GM(analytic_antialias_inverse, canvas, W, H) {

View File

@ -8,7 +8,7 @@
#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/SkRect.h"
#include "include/core/SkScalar.h"
@ -35,11 +35,10 @@ DEF_SIMPLE_GM(bug5252, canvas, 500, 500) {
canvas->translate(i * 15.f, j * 20.f);
canvas->drawRect(SkRect::MakeXYWH(5, 5, 10, 15),pa);
SkPath path;
path.moveTo(6, 6);
path.cubicTo(14, 10, 13, 12, 10, 12);
path.cubicTo(7, 15, 8, 17, 14, 18);
canvas->drawPath(path, pa);
canvas->drawPath(SkPathBuilder().moveTo(6, 6)
.cubicTo(14, 10, 13, 12, 10, 12)
.cubicTo(7, 15, 8, 17, 14, 18)
.detach(), pa);
}
}
}

View File

@ -334,7 +334,7 @@ void test_coincident_edges_2(SkCanvas* canvas, const SkPaint& paint) {
}
// Coincident edges (small ones first, coincident vert on bottom).
void test_coincident_edges_3(SkCanvas* canvas, const SkPaint& paint) {
SkPath path;
SkPathBuilder path;
canvas->save();
canvas->translate(200, 500);
path.moveTo(20, 80);
@ -343,12 +343,12 @@ void test_coincident_edges_3(SkCanvas* canvas, const SkPaint& paint) {
path.moveTo(20, 80);
path.lineTo(20, 20);
path.lineTo(80, 20);
canvas->drawPath(path, paint);
canvas->drawPath(path.detach(), paint);
canvas->restore();
}
// Coincident edges (big ones first, coincident vert on bottom).
void test_coincident_edges_4(SkCanvas* canvas, const SkPaint& paint) {
SkPath path;
SkPathBuilder path;
canvas->save();
canvas->translate(300, 500);
path.moveTo(20, 80);
@ -357,7 +357,7 @@ void test_coincident_edges_4(SkCanvas* canvas, const SkPaint& paint) {
path.moveTo(20, 80);
path.lineTo(20, 50);
path.lineTo(50, 50);
canvas->drawPath(path, paint);
canvas->drawPath(path.detach(), paint);
canvas->restore();
}

View File

@ -10,7 +10,7 @@
#include "include/core/SkColor.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPath.h"
#include "include/core/SkPathBuilder.h"
#include "include/core/SkRect.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSize.h"
@ -53,214 +53,171 @@ class ConvexPathsGM : public skiagm::GM {
}
fOnce.accomplished();
fPaths.push_back().moveTo(0, 0);
fPaths.back().quadTo(50 * SK_Scalar1, 100 * SK_Scalar1,
0, 100 * SK_Scalar1);
fPaths.back().lineTo(0, 0);
SkPathBuilder b;
fPaths.push_back(b.moveTo(0, 0)
.quadTo(50, 100, 0, 100)
.lineTo(0, 0)
.detach());
fPaths.push_back().moveTo(0, 50 * SK_Scalar1);
fPaths.back().quadTo(50 * SK_Scalar1, 0,
100 * SK_Scalar1, 50 * SK_Scalar1);
fPaths.back().quadTo(50 * SK_Scalar1, 100 * SK_Scalar1,
0, 50 * SK_Scalar1);
fPaths.push_back(b.moveTo(0, 50)
.quadTo(50, 0, 100, 50)
.quadTo(50, 100, 0, 50)
.detach());
fPaths.push_back().addRect(0, 0,
100 * SK_Scalar1, 100 * SK_Scalar1,
SkPathDirection::kCW);
fPaths.push_back().addRect(0, 0,
100 * SK_Scalar1, 100 * SK_Scalar1,
SkPathDirection::kCCW);
fPaths.push_back().addCircle(50 * SK_Scalar1, 50 * SK_Scalar1,
50 * SK_Scalar1, SkPathDirection::kCW);
fPaths.push_back().addOval(SkRect::MakeXYWH(0, 0,
50 * SK_Scalar1,
100 * SK_Scalar1),
SkPathDirection::kCW);
fPaths.push_back().addOval(SkRect::MakeXYWH(0, 0,
100 * SK_Scalar1,
5 * SK_Scalar1),
SkPathDirection::kCCW);
fPaths.push_back().addOval(SkRect::MakeXYWH(0, 0,
SK_Scalar1,
100 * SK_Scalar1),
SkPathDirection::kCCW);
fPaths.push_back().addRoundRect(SkRect::MakeXYWH(0, 0,
SK_Scalar1 * 100,
SK_Scalar1 * 100),
40 * SK_Scalar1, 20 * SK_Scalar1,
SkPathDirection::kCW);
fPaths.push_back(SkPath::Rect({0, 0, 100, 100}, SkPathDirection::kCW));
fPaths.push_back(SkPath::Rect({0, 0, 100, 100}, SkPathDirection::kCCW));
fPaths.push_back(SkPath::Circle(50, 50, 50, SkPathDirection::kCW));
fPaths.push_back(SkPath::Oval(SkRect::MakeXYWH(0, 0, 50, 100), SkPathDirection::kCW));
fPaths.push_back(SkPath::Oval(SkRect::MakeXYWH(0, 0, 100, 5), SkPathDirection::kCCW));
fPaths.push_back(SkPath::Oval(SkRect::MakeXYWH(0, 0, 1, 100), SkPathDirection::kCCW));
fPaths.push_back(SkPath::RRect(SkRRect::MakeRectXY({0, 0, 100, 100}, 40, 20),
SkPathDirection::kCW));
// large number of points
enum {
kLength = 100,
kPtsPerSide = (1 << 12),
};
fPaths.push_back().moveTo(0, 0);
b.moveTo(0, 0);
for (int i = 1; i < kPtsPerSide; ++i) { // skip the first point due to moveTo.
fPaths.back().lineTo(kLength * SkIntToScalar(i) / kPtsPerSide, 0);
b.lineTo(kLength * SkIntToScalar(i) / kPtsPerSide, 0);
}
for (int i = 0; i < kPtsPerSide; ++i) {
fPaths.back().lineTo(kLength, kLength * SkIntToScalar(i) / kPtsPerSide);
b.lineTo(kLength, kLength * SkIntToScalar(i) / kPtsPerSide);
}
for (int i = kPtsPerSide; i > 0; --i) {
fPaths.back().lineTo(kLength * SkIntToScalar(i) / kPtsPerSide, kLength);
b.lineTo(kLength * SkIntToScalar(i) / kPtsPerSide, kLength);
}
for (int i = kPtsPerSide; i > 0; --i) {
fPaths.back().lineTo(0, kLength * SkIntToScalar(i) / kPtsPerSide);
b.lineTo(0, kLength * SkIntToScalar(i) / kPtsPerSide);
}
fPaths.push_back(b.detach());
// shallow diagonals
fPaths.push_back().lineTo(100 * SK_Scalar1, SK_Scalar1);
fPaths.back().lineTo(98 * SK_Scalar1, 100 * SK_Scalar1);
fPaths.back().lineTo(3 * SK_Scalar1, 96 * SK_Scalar1);
fPaths.push_back(SkPath::Polygon({{0,0}, {100,1}, {98,100}, {3,96}}, false));
fPaths.push_back().arcTo(SkRect::MakeXYWH(0, 0,
50 * SK_Scalar1,
100 * SK_Scalar1),
25 * SK_Scalar1, 130 * SK_Scalar1, false);
fPaths.push_back(b.arcTo(SkRect::MakeXYWH(0, 0, 50, 100), 25, 130, false)
.detach());
// cubics
fPaths.push_back().cubicTo( 1 * SK_Scalar1, 1 * SK_Scalar1,
10 * SK_Scalar1, 90 * SK_Scalar1,
0 * SK_Scalar1, 100 * SK_Scalar1);
fPaths.push_back().cubicTo(100 * SK_Scalar1, 50 * SK_Scalar1,
20 * SK_Scalar1, 100 * SK_Scalar1,
0 * SK_Scalar1, 0 * SK_Scalar1);
fPaths.push_back(b.cubicTo( 1, 1, 10, 90, 0, 100).detach());
fPaths.push_back(b.cubicTo(100, 50, 20, 100, 0, 0).detach());
// path that has a cubic with a repeated first control point and
// a repeated last control point.
fPaths.push_back().moveTo(SK_Scalar1 * 10, SK_Scalar1 * 10);
fPaths.back().cubicTo(10 * SK_Scalar1, 10 * SK_Scalar1,
10 * SK_Scalar1, 0,
20 * SK_Scalar1, 0);
fPaths.back().lineTo(40 * SK_Scalar1, 0);
fPaths.back().cubicTo(40 * SK_Scalar1, 0,
50 * SK_Scalar1, 0,
50 * SK_Scalar1, 10 * SK_Scalar1);
fPaths.push_back(b.moveTo(10, 10)
.cubicTo(10, 10, 10, 0, 20, 0)
.lineTo(40, 0)
.cubicTo(40, 0, 50, 0, 50, 10)
.detach());
// path that has two cubics with repeated middle control points.
fPaths.push_back().moveTo(SK_Scalar1 * 10, SK_Scalar1 * 10);
fPaths.back().cubicTo(10 * SK_Scalar1, 0,
10 * SK_Scalar1, 0,
20 * SK_Scalar1, 0);
fPaths.back().lineTo(40 * SK_Scalar1, 0);
fPaths.back().cubicTo(50 * SK_Scalar1, 0,
50 * SK_Scalar1, 0,
50 * SK_Scalar1, 10 * SK_Scalar1);
fPaths.push_back(b.moveTo(10, 10)
.cubicTo(10, 0, 10, 0, 20, 0)
.lineTo(40, 0)
.cubicTo(50, 0, 50, 0, 50, 10)
.detach());
// cubic where last three points are almost a line
fPaths.push_back().moveTo(0, 228 * SK_Scalar1 / 8);
fPaths.back().cubicTo(628 * SK_Scalar1 / 8, 82 * SK_Scalar1 / 8,
1255 * SK_Scalar1 / 8, 141 * SK_Scalar1 / 8,
1883 * SK_Scalar1 / 8, 202 * SK_Scalar1 / 8);
fPaths.push_back(b.moveTo(0, 228.0f/8)
.cubicTo( 628.0f/ 8, 82.0f/8,
1255.0f/ 8, 141.0f/8,
1883.0f/ 8, 202.0f/8)
.detach());
// flat cubic where the at end point tangents both point outward.
fPaths.push_back().moveTo(10 * SK_Scalar1, 0);
fPaths.back().cubicTo(0, SK_Scalar1,
30 * SK_Scalar1, SK_Scalar1,
20 * SK_Scalar1, 0);
fPaths.push_back(b.moveTo(10, 0)
.cubicTo(0, 1, 30, 1, 20, 0)
.detach());
// flat cubic where initial tangent is in, end tangent out
fPaths.push_back().moveTo(0, 0 * SK_Scalar1);
fPaths.back().cubicTo(10 * SK_Scalar1, SK_Scalar1,
30 * SK_Scalar1, SK_Scalar1,
20 * SK_Scalar1, 0);
fPaths.push_back(b.moveTo(0, 0)
.cubicTo(10, 1, 30, 1, 20, 0)
.detach());
// flat cubic where initial tangent is out, end tangent in
fPaths.push_back().moveTo(10 * SK_Scalar1, 0);
fPaths.back().cubicTo(0, SK_Scalar1,
20 * SK_Scalar1, SK_Scalar1,
30 * SK_Scalar1, 0);
fPaths.push_back(b.moveTo(10, 0)
.cubicTo(0, 1, 20, 1, 30, 0)
.detach());
// triangle where one edge is a degenerate quad
fPaths.push_back().moveTo(8.59375f, 45 * SK_Scalar1);
fPaths.back().quadTo(16.9921875f, 45 * SK_Scalar1,
31.25f, 45 * SK_Scalar1);
fPaths.back().lineTo(100 * SK_Scalar1, 100 * SK_Scalar1);
fPaths.back().lineTo(8.59375f, 45 * SK_Scalar1);
fPaths.push_back(b.moveTo(8.59375f, 45)
.quadTo(16.9921875f, 45,
31.25f, 45)
.lineTo(100, 100)
.lineTo(8.59375f, 45)
.detach());
// triangle where one edge is a quad with a repeated point
fPaths.push_back().moveTo(0, 25 * SK_Scalar1);
fPaths.back().lineTo(50 * SK_Scalar1, 0);
fPaths.back().quadTo(50 * SK_Scalar1, 50 * SK_Scalar1, 50 * SK_Scalar1, 50 * SK_Scalar1);
fPaths.push_back(b.moveTo(0, 25)
.lineTo(50, 0)
.quadTo(50, 50, 50, 50)
.detach());
// triangle where one edge is a cubic with a 2x repeated point
fPaths.push_back().moveTo(0, 25 * SK_Scalar1);
fPaths.back().lineTo(50 * SK_Scalar1, 0);
fPaths.back().cubicTo(50 * SK_Scalar1, 0,
50 * SK_Scalar1, 50 * SK_Scalar1,
50 * SK_Scalar1, 50 * SK_Scalar1);
fPaths.push_back(b.moveTo(0, 25)
.lineTo(50, 0)
.cubicTo(50, 0, 50, 50, 50, 50)
.detach());
// triangle where one edge is a quad with a nearly repeated point
fPaths.push_back().moveTo(0, 25 * SK_Scalar1);
fPaths.back().lineTo(50 * SK_Scalar1, 0);
fPaths.back().quadTo(50 * SK_Scalar1, 49.95f,
50 * SK_Scalar1, 50 * SK_Scalar1);
fPaths.push_back(b.moveTo(0, 25)
.lineTo(50, 0)
.quadTo(50, 49.95f, 50, 50)
.detach());
// triangle where one edge is a cubic with a 3x nearly repeated point
fPaths.push_back().moveTo(0, 25 * SK_Scalar1);
fPaths.back().lineTo(50 * SK_Scalar1, 0);
fPaths.back().cubicTo(50 * SK_Scalar1, 49.95f,
50 * SK_Scalar1, 49.97f,
50 * SK_Scalar1, 50 * SK_Scalar1);
fPaths.push_back(b.moveTo(0, 25)
.lineTo(50, 0)
.cubicTo(50, 49.95f, 50, 49.97f, 50, 50)
.detach());
// triangle where there is a point degenerate cubic at one corner
fPaths.push_back().moveTo(0, 25 * SK_Scalar1);
fPaths.back().lineTo(50 * SK_Scalar1, 0);
fPaths.back().lineTo(50 * SK_Scalar1, 50 * SK_Scalar1);
fPaths.back().cubicTo(50 * SK_Scalar1, 50 * SK_Scalar1,
50 * SK_Scalar1, 50 * SK_Scalar1,
50 * SK_Scalar1, 50 * SK_Scalar1);
fPaths.push_back(b.moveTo(0, 25)
.lineTo(50, 0)
.lineTo(50, 50)
.cubicTo(50, 50, 50, 50, 50, 50)
.detach());
// point line
fPaths.push_back().moveTo(50 * SK_Scalar1, 50 * SK_Scalar1);
fPaths.back().lineTo(50 * SK_Scalar1, 50 * SK_Scalar1);
fPaths.push_back(SkPath::Line({50, 50}, {50, 50}));
// point quad
fPaths.push_back().moveTo(50 * SK_Scalar1, 50 * SK_Scalar1);
fPaths.back().quadTo(50 * SK_Scalar1, 50 * SK_Scalar1,
50 * SK_Scalar1, 50 * SK_Scalar1);
fPaths.push_back(b.moveTo(50, 50)
.quadTo(50, 50, 50, 50)
.detach());
// point cubic
fPaths.push_back().moveTo(50 * SK_Scalar1, 50 * SK_Scalar1);
fPaths.back().cubicTo(50 * SK_Scalar1, 50 * SK_Scalar1,
50 * SK_Scalar1, 50 * SK_Scalar1,
50 * SK_Scalar1, 50 * SK_Scalar1);
fPaths.push_back(b.moveTo(50, 50)
.cubicTo(50, 50, 50, 50, 50, 50)
.detach());
// moveTo only paths
fPaths.push_back().moveTo(0, 0);
fPaths.back().moveTo(0, 0);
fPaths.back().moveTo(SK_Scalar1, SK_Scalar1);
fPaths.back().moveTo(SK_Scalar1, SK_Scalar1);
fPaths.back().moveTo(10 * SK_Scalar1, 10 * SK_Scalar1);
fPaths.push_back(b.moveTo(0, 0)
.moveTo(0, 0)
.moveTo(1, 1)
.moveTo(1, 1)
.moveTo(10, 10)
.detach());
fPaths.push_back().moveTo(0, 0);
fPaths.back().moveTo(0, 0);
fPaths.push_back(b.moveTo(0, 0)
.moveTo(0, 0)
.detach());
// line degenerate
fPaths.push_back().lineTo(100 * SK_Scalar1, 100 * SK_Scalar1);
fPaths.push_back().quadTo(100 * SK_Scalar1, 100 * SK_Scalar1, 0, 0);
fPaths.push_back().quadTo(100 * SK_Scalar1, 100 * SK_Scalar1,
50 * SK_Scalar1, 50 * SK_Scalar1);
fPaths.push_back().quadTo(50 * SK_Scalar1, 50 * SK_Scalar1,
100 * SK_Scalar1, 100 * SK_Scalar1);
fPaths.push_back().cubicTo(0, 0,
0, 0,
100 * SK_Scalar1, 100 * SK_Scalar1);
fPaths.push_back(b.lineTo(100, 100).detach());
fPaths.push_back(b.quadTo(100, 100, 0, 0).detach());
fPaths.push_back(b.quadTo(100, 100, 50, 50).detach());
fPaths.push_back(b.quadTo(50, 50, 100, 100).detach());
fPaths.push_back(b.cubicTo(0, 0, 0, 0, 100, 100).detach());
// skbug.com/8928
fPaths.push_back().moveTo(16.875f, 192.594f);
fPaths.back().cubicTo(45.625f, 192.594f, 74.375f, 192.594f, 103.125f, 192.594f);
fPaths.back().cubicTo(88.75f, 167.708f, 74.375f, 142.823f, 60, 117.938f);
fPaths.back().cubicTo(45.625f, 142.823f, 31.25f, 167.708f, 16.875f, 192.594f);
fPaths.back().close();
fPaths.push_back(b.moveTo(16.875f, 192.594f)
.cubicTo(45.625f, 192.594f, 74.375f, 192.594f, 103.125f, 192.594f)
.cubicTo(88.75f, 167.708f, 74.375f, 142.823f, 60, 117.938f)
.cubicTo(45.625f, 142.823f, 31.25f, 167.708f, 16.875f, 192.594f)
.close()
.detach());
SkMatrix m;
m.setAll(0.1f, 0, -1, 0, 0.115207f, -2.64977f, 0, 0, 1);
fPaths.back().transform(m);
@ -276,16 +233,16 @@ class ConvexPathsGM : public skiagm::GM {
SkPaint paint;
paint.setAntiAlias(true);
SkRandom rand;
canvas->translate(20 * SK_Scalar1, 20 * SK_Scalar1);
canvas->translate(20, 20);
// As we've added more paths this has gotten pretty big. Scale the whole thing down.
canvas->scale(2 * SK_Scalar1 / 3, 2 * SK_Scalar1 / 3);
canvas->scale(2.0f/3, 2.0f/3);
for (int i = 0; i < fPaths.count(); ++i) {
canvas->save();
// position the path, and make it at off-integer coords.
canvas->translate(SK_Scalar1 * 200 * (i % 5) + SK_Scalar1 / 10,
SK_Scalar1 * 200 * (i / 5) + 9 * SK_Scalar1 / 10);
canvas->translate(200.0f * (i % 5) + 1.0f/10,
200.0f * (i / 5) + 9.0f/10);
SkColor color = rand.nextU();
color |= 0xff000000;
paint.setColor(color);

View File

@ -12,9 +12,7 @@
#include "include/effects/SkDashPathEffect.h"
DEF_SIMPLE_GM(crbug_1113794, canvas, 600, 200) {
SkPath path;
path.moveTo(50.f, 80.f);
path.lineTo(50.f, 20.f);
SkPath path = SkPath::Line({50.f, 80.f}, {50.f, 20.f});
SkPaint paint;
paint.setColor(SK_ColorBLACK);

View File

@ -1816,7 +1816,7 @@ public:
bool isValid() const { return this->isValidImpl() && fPathRef->isValid(); }
private:
SkPath(sk_sp<SkPathRef>, SkPathFillType, bool isVolatile);
SkPath(sk_sp<SkPathRef>, SkPathFillType, bool isVolatile, SkPathConvexityType);
sk_sp<SkPathRef> fPathRef;
int fLastMoveToIndex;

View File

@ -216,6 +216,9 @@ private:
int fIsAStart = -1; // tracks direction iff fIsA is not unknown
bool fIsACCW = false; // tracks direction iff fIsA is not unknown
// for testing
SkPathConvexityType fConvexity = SkPathConvexityType::kUnknown;
int countVerbs() const { return fVerbs.count(); }
// called right before we add a (non-move) verb
@ -227,6 +230,11 @@ private:
}
SkPath make(sk_sp<SkPathRef>) const;
// For testing
void privateSetConvexityType(SkPathConvexityType c) { fConvexity = c; }
friend class SkPathPriv;
};
#endif

View File

@ -6,6 +6,7 @@
*/
#include "include/core/SkContourMeasure.h"
#include "include/core/SkPathBuilder.h"
#include "modules/skottie/src/SkottieJson.h"
#include "modules/skottie/src/SkottieValue.h"
#include "modules/skottie/src/animator/Animator.h"
@ -88,12 +89,12 @@ public:
}
// Finally, this looks like a legitimate spatial keyframe.
SkPath p;
SkPathBuilder p;
p.moveTo (prev_val.v2.x , prev_val.v2.y);
p.cubicTo(prev_val.v2.x + fTo.x, prev_val.v2.y + fTo.y,
val.v2.x + fTi.x, val.v2.y + fTi.y,
val.v2.x, val.v2.y);
prev_val.cmeasure = SkContourMeasureIter(p, false).next();
prev_val.cmeasure = SkContourMeasureIter(p.detach(), false).next();
}
bool parseKFValue(const AnimationBuilder&,

View File

@ -6,6 +6,7 @@
*/
#include "include/core/SkCanvas.h"
#include "include/core/SkPathBuilder.h"
#include "include/core/SkRRect.h"
#include "include/utils/SkRandom.h"
#include "samplecode/Sample.h"
@ -102,20 +103,20 @@ protected:
SkVector::Make(0, 0));
// Background decoration.
SkPath bgPath;
bgPath.moveTo(kBounds.left() , fieldBounds.top());
bgPath.lineTo(kBounds.right(), fieldBounds.top());
bgPath.moveTo(kBounds.left() , fieldBounds.bottom());
bgPath.lineTo(kBounds.right(), fieldBounds.bottom());
SkPathBuilder bgPath;
bgPath.moveTo(kBounds.left() , fieldBounds.top())
.lineTo(kBounds.right(), fieldBounds.top())
.moveTo(kBounds.left() , fieldBounds.bottom())
.lineTo(kBounds.right(), fieldBounds.bottom());
// TODO: stroke-dash support would come in handy right about now.
for (uint32_t i = 0; i < kBackgroundDashCount; ++i) {
bgPath.moveTo(kBounds.centerX(),
kBounds.top() + (i + 0.25f) * kBounds.height() / kBackgroundDashCount);
bgPath.lineTo(kBounds.centerX(),
kBounds.top() + (i + 0.25f) * kBounds.height() / kBackgroundDashCount)
.lineTo(kBounds.centerX(),
kBounds.top() + (i + 0.75f) * kBounds.height() / kBackgroundDashCount);
}
auto bg_path = sksg::Path::Make(bgPath);
auto bg_path = sksg::Path::Make(bgPath.detach());
auto bg_paint = sksg::Color::Make(SK_ColorBLACK);
bg_paint->setStyle(SkPaint::kStroke_Style);
bg_paint->setStrokeWidth(kBackgroundStroke);

View File

@ -147,10 +147,10 @@ SkPath::SkPath()
fIsVolatile = false;
}
SkPath::SkPath(sk_sp<SkPathRef> pr, SkPathFillType ft, bool isVolatile)
SkPath::SkPath(sk_sp<SkPathRef> pr, SkPathFillType ft, bool isVolatile, SkPathConvexityType ct)
: fPathRef(std::move(pr))
, fLastMoveToIndex(INITIAL_LASTMOVETOINDEX_VALUE)
, fConvexity((uint8_t)SkPathConvexityType::kUnknown)
, fConvexity((uint8_t)ct)
, fFirstDirection(SkPathPriv::kUnknown_FirstDirection)
, fFillType((unsigned)ft)
, fIsVolatile(isVolatile)
@ -3402,7 +3402,7 @@ SkPath SkPath::Make(const SkPoint pts[], int pointCount,
SkTDArray<uint8_t>(vbs, verbCount),
SkTDArray<SkScalar>(ws, info.weights),
info.segmentMask)),
ft, isVolatile);
ft, isVolatile, SkPathConvexityType::kUnknown);
}
SkPath SkPath::Rect(const SkRect& r, SkPathDirection dir) {

View File

@ -32,6 +32,7 @@ SkPathBuilder& SkPathBuilder::reset() {
fSegmentMask = 0;
fLastMovePoint = {0, 0};
fNeedsMoveVerb = true;
fConvexity = SkPathConvexityType::kUnknown;
return *this;
}
@ -149,7 +150,7 @@ SkPath SkPathBuilder::make(sk_sp<SkPathRef> pr) const {
case kIsA_RRect: pr->setIsRRect(true, fIsACCW, fIsAStart); break;
default: break;
}
return SkPath(std::move(pr), fFillType, fIsVolatile);
return SkPath(std::move(pr), fFillType, fIsVolatile, fConvexity);
}
SkPath SkPathBuilder::snapshot() {

View File

@ -8,7 +8,7 @@
#ifndef SkPathPriv_DEFINED
#define SkPathPriv_DEFINED
#include "include/core/SkPath.h"
#include "include/core/SkPathBuilder.h"
#include "include/private/SkIDChangeListener.h"
#include "src/core/SkPathView.h"
@ -392,6 +392,10 @@ public:
ed.writablePoints()[index] = pt;
path->dirtyAfterEdit();
}
static void SetConvexityType(SkPathBuilder* builder, SkPathConvexityType c) {
builder->privateSetConvexityType(c);
}
};
// Lightweight variant of SkPath::Iter that only returns segments (e.g. lines/conics).