use pathbuilder

Change-Id: Icb4d3f98440b53ba38270cc1f43fc43e6724d36b
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/315736
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Mike Reed <reed@google.com>
This commit is contained in:
Mike Reed 2020-09-08 20:47:09 -04:00 committed by Skia Commit-Bot
parent 81c6d6eeb4
commit d849a75ad3
7 changed files with 137 additions and 112 deletions

View File

@ -12,7 +12,7 @@
#include "include/core/SkFont.h"
#include "include/core/SkFontTypes.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"
@ -54,21 +54,22 @@ protected:
SkISize onISize() override { return SkISize::Make(388, 780); }
void onDraw(SkCanvas* canvas) override {
SkPath path;
path.moveTo(0, 50)
.quadTo(0, 0, 50, 0)
.lineTo(175, 0)
.quadTo(200, 0, 200, 25)
.lineTo(200, 150)
.quadTo(200, 200, 150, 200)
.lineTo(0, 200)
.close()
.moveTo(50, 50)
.lineTo(150, 50)
.lineTo(150, 125)
.quadTo(150, 150, 125, 150)
.lineTo(50, 150)
.close();
SkPath path = SkPathBuilder()
.moveTo(0, 50)
.quadTo(0, 0, 50, 0)
.lineTo(175, 0)
.quadTo(200, 0, 200, 25)
.lineTo(200, 150)
.quadTo(200, 200, 150, 200)
.lineTo(0, 200)
.close()
.moveTo(50, 50)
.lineTo(150, 50)
.lineTo(150, 125)
.quadTo(150, 150, 125, 150)
.lineTo(50, 150)
.close()
.detach();
if (fInvertDraw) {
path.setFillType(SkPathFillType::kInverseEvenOdd);
} else {
@ -78,11 +79,9 @@ protected:
pathPaint.setAntiAlias(true);
pathPaint.setColor(gPathColor);
SkPath clipA;
clipA.addPoly({{10, 20}, {165, 22}, {70, 105}, {165, 177}, {-5, 180}}, false).close();
SkPath clipA = SkPath::Polygon({{10, 20}, {165, 22}, {70, 105}, {165, 177}, {-5, 180}}, true);
SkPath clipB;
clipB.addPoly({{40, 10}, {190, 15}, {195, 190}, {40, 185}, {155, 100}}, false).close();
SkPath clipB = SkPath::Polygon({{40, 10}, {190, 15}, {195, 190}, {40, 185}, {155, 100}}, true);
SkFont font(ToolUtils::create_portable_typeface(), 20);

View File

@ -207,8 +207,7 @@ protected:
canvas->save();
}
canvas->translate(x, y);
SkPath closedClipPath;
clip->asClosedPath(&closedClipPath);
SkPath closedClipPath = clip->asClosedPath();
canvas->drawPath(closedClipPath, clipOutlinePaint);
clip->setOnCanvas(canvas, kIntersect_SkClipOp, SkToBool(aa));
canvas->scale(1.f, 1.8f);
@ -240,7 +239,7 @@ private:
void setOnCanvas(SkCanvas* canvas, SkClipOp op, bool aa) const {
switch (fClipType) {
case kPath_ClipType:
canvas->clipPath(fPath, op, aa);
canvas->clipPath(fPathBuilder.snapshot(), op, aa);
break;
case kRect_ClipType:
canvas->clipRect(fRect, op, aa);
@ -251,31 +250,29 @@ private:
}
}
void asClosedPath(SkPath* path) const {
SkPath asClosedPath() const {
switch (fClipType) {
case kPath_ClipType:
*path = fPath;
path->close();
return SkPathBuilder(fPathBuilder).close().detach();
break;
case kRect_ClipType:
path->reset();
path->addRect(fRect);
break;
return SkPath::Rect(fRect);
case kNone_ClipType:
SkDEBUGFAIL("Uninitialized Clip.");
break;
}
return SkPath();
}
void setPath(const SkPath& path) {
fClipType = kPath_ClipType;
fPath = path;
fPathBuilder = path;
}
void setRect(const SkRect& rect) {
fClipType = kRect_ClipType;
fRect = rect;
fPath.reset();
fPathBuilder.reset();
}
ClipType getType() const { return fClipType; }
@ -283,7 +280,7 @@ private:
void getBounds(SkRect* bounds) const {
switch (fClipType) {
case kPath_ClipType:
*bounds = fPath.getBounds();
*bounds = fPathBuilder.computeBounds();
break;
case kRect_ClipType:
*bounds = fRect;
@ -296,7 +293,7 @@ private:
private:
ClipType fClipType;
SkPath fPath;
SkPathBuilder fPathBuilder;
SkRect fRect;
};

View File

@ -16,9 +16,18 @@
class SK_API SkPathBuilder {
public:
SkPathBuilder();
SkPathBuilder(SkPathFillType);
SkPathBuilder(const SkPath&);
SkPathBuilder(const SkPathBuilder&) = default;
~SkPathBuilder();
SkPath snapshot(); // the builder is unchanged after returning this path
SkPathBuilder& operator=(const SkPath&);
SkPathBuilder& operator=(const SkPathBuilder&) = default;
SkPathFillType fillType() const { return fFillType; }
SkRect computeBounds() const;
SkPath snapshot() const; // the builder is unchanged after returning this path
SkPath detach(); // the builder is reset to empty after returning this path
SkPathBuilder& setFillType(SkPathFillType ft) { fFillType = ft; return *this; }

View File

@ -18,6 +18,10 @@ SkPathBuilder::SkPathBuilder() {
this->reset();
}
SkPathBuilder::SkPathBuilder(const SkPath& src) {
*this = src;
}
SkPathBuilder::~SkPathBuilder() {
}
@ -40,11 +44,33 @@ SkPathBuilder& SkPathBuilder::reset() {
return *this;
}
SkPathBuilder& SkPathBuilder::operator=(const SkPath& src) {
this->reset().setFillType(src.getFillType());
for (auto [verb, pts, w] : SkPathPriv::Iterate(src)) {
switch (verb) {
case SkPathVerb::kMove: this->moveTo(pts[0]); break;
case SkPathVerb::kLine: this->lineTo(pts[1]); break;
case SkPathVerb::kQuad: this->quadTo(pts[1], pts[2]); break;
case SkPathVerb::kConic: this->conicTo(pts[1], pts[2], w[0]); break;
case SkPathVerb::kCubic: this->cubicTo(pts[1], pts[2], pts[3]); break;
case SkPathVerb::kClose: this->close(); break;
}
}
return *this;
}
void SkPathBuilder::incReserve(int extraPtCount, int extraVbCount) {
fPts.setReserve( Sk32_sat_add(fPts.count(), extraPtCount));
fVerbs.setReserve(Sk32_sat_add(fVerbs.count(), extraVbCount));
}
SkRect SkPathBuilder::computeBounds() const {
SkRect bounds;
bounds.setBounds(fPts.begin(), fPts.count());
return bounds;
}
/*
* Some old behavior in SkPath -- should we keep it?
*
@ -178,7 +204,7 @@ SkPath SkPathBuilder::make(sk_sp<SkPathRef> pr) const {
return SkPath(std::move(pr), fFillType, fIsVolatile, convexity, dir);
}
SkPath SkPathBuilder::snapshot() {
SkPath SkPathBuilder::snapshot() const {
return this->make(sk_sp<SkPathRef>(new SkPathRef(fPts,
fVerbs,
fConicWeights,

View File

@ -675,10 +675,10 @@ GrReducedClip::ClipResult GrReducedClip::addAnalyticRRect(const SkRRect& deviceS
return ClipResult::kClipped;
}
SkPath deviceSpacePath;
SkPathBuilder deviceSpacePath;
deviceSpacePath.setIsVolatile(true);
deviceSpacePath.addRRect(deviceSpaceRRect);
return this->addAnalyticPath(deviceSpacePath, invert, aa);
return this->addAnalyticPath(deviceSpacePath.detach(), invert, aa);
}
GrReducedClip::ClipResult GrReducedClip::addAnalyticPath(const SkPath& deviceSpacePath,

View File

@ -8,7 +8,7 @@
#include "src/gpu/GrTestUtils.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPath.h"
#include "include/core/SkPathBuilder.h"
#include "include/core/SkRRect.h"
#include "src/core/SkRectPriv.h"
#include "src/gpu/GrColorInfo.h"
@ -168,36 +168,43 @@ const SkPath& TestPath(SkRandom* random) {
if (!gOnce) {
gOnce = true;
// line
gPath[0].moveTo(0.f, 0.f);
gPath[0].lineTo(10.f, 10.f);
gPath[0] = SkPathBuilder().moveTo(0.f, 0.f)
.lineTo(10.f, 10.f)
.detach();
// quad
gPath[1].moveTo(0.f, 0.f);
gPath[1].quadTo(10.f, 10.f, 20.f, 20.f);
gPath[1] = SkPathBuilder().moveTo(0.f, 0.f)
.quadTo(10.f, 10.f, 20.f, 20.f)
.detach();
// conic
gPath[2].moveTo(0.f, 0.f);
gPath[2].conicTo(10.f, 10.f, 20.f, 20.f, 1.f);
gPath[2] = SkPathBuilder().moveTo(0.f, 0.f)
.conicTo(10.f, 10.f, 20.f, 20.f, 1.f)
.detach();
// cubic
gPath[3].moveTo(0.f, 0.f);
gPath[3].cubicTo(10.f, 10.f, 20.f, 20.f, 30.f, 30.f);
gPath[3] = SkPathBuilder().moveTo(0.f, 0.f)
.cubicTo(10.f, 10.f, 20.f, 20.f, 30.f, 30.f)
.detach();
// all three
gPath[4].moveTo(0.f, 0.f);
gPath[4].lineTo(10.f, 10.f);
gPath[4].quadTo(10.f, 10.f, 20.f, 20.f);
gPath[4].conicTo(10.f, 10.f, 20.f, 20.f, 1.f);
gPath[4].cubicTo(10.f, 10.f, 20.f, 20.f, 30.f, 30.f);
gPath[4] = SkPathBuilder().moveTo(0.f, 0.f)
.lineTo(10.f, 10.f)
.quadTo(10.f, 10.f, 20.f, 20.f)
.conicTo(10.f, 10.f, 20.f, 20.f, 1.f)
.cubicTo(10.f, 10.f, 20.f, 20.f, 30.f, 30.f)
.detach();
// convex
gPath[5].moveTo(0.0f, 0.0f);
gPath[5].lineTo(10.0f, 0.0f);
gPath[5].lineTo(10.0f, 10.0f);
gPath[5].lineTo(0.0f, 10.0f);
gPath[5].close();
gPath[5] = SkPathBuilder().moveTo(0.0f, 0.0f)
.lineTo(10.0f, 0.0f)
.lineTo(10.0f, 10.0f)
.lineTo(0.0f, 10.0f)
.close()
.detach();
// concave
gPath[6].moveTo(0.0f, 0.0f);
gPath[6].lineTo(5.0f, 5.0f);
gPath[6].lineTo(10.0f, 0.0f);
gPath[6].lineTo(10.0f, 10.0f);
gPath[6].lineTo(0.0f, 10.0f);
gPath[6].close();
gPath[6] = SkPathBuilder().moveTo(0.0f, 0.0f)
.lineTo(5.0f, 5.0f)
.lineTo(10.0f, 0.0f)
.lineTo(10.0f, 10.0f)
.lineTo(0.0f, 10.0f)
.close()
.detach();
}
return gPath[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gPath)))];
@ -209,25 +216,25 @@ const SkPath& TestPathConvex(SkRandom* random) {
if (!gOnce) {
gOnce = true;
// narrow rect
gPath[0].moveTo(-1.5f, -50.0f);
gPath[0].lineTo(-1.5f, -50.0f);
gPath[0].lineTo( 1.5f, -50.0f);
gPath[0].lineTo( 1.5f, 50.0f);
gPath[0].lineTo(-1.5f, 50.0f);
gPath[0] = SkPath::Polygon({{-1.5f, -50.0f},
{-1.5f, -50.0f},
{ 1.5f, -50.0f},
{ 1.5f, 50.0f},
{-1.5f, 50.0f}}, false);
// degenerate
gPath[1].moveTo(-0.025f, -0.025f);
gPath[1].lineTo(-0.025f, -0.025f);
gPath[1].lineTo( 0.025f, -0.025f);
gPath[1].lineTo( 0.025f, 0.025f);
gPath[1].lineTo(-0.025f, 0.025f);
gPath[1] = SkPath::Polygon({{-0.025f, -0.025f},
{-0.025f, -0.025f},
{ 0.025f, -0.025f},
{ 0.025f, 0.025f},
{-0.025f, 0.025f}}, false);
// clipped triangle
gPath[2].moveTo(-10.0f, -50.0f);
gPath[2].lineTo(-10.0f, -50.0f);
gPath[2].lineTo( 10.0f, -50.0f);
gPath[2].lineTo( 50.0f, 31.0f);
gPath[2].lineTo( 40.0f, 50.0f);
gPath[2].lineTo(-40.0f, 50.0f);
gPath[2].lineTo(-50.0f, 31.0f);
gPath[2] = SkPath::Polygon({{-10.0f, -50.0f},
{-10.0f, -50.0f},
{ 10.0f, -50.0f},
{ 50.0f, 31.0f},
{ 40.0f, 50.0f},
{-40.0f, 50.0f},
{-50.0f, 31.0f}}, false);
for (size_t i = 0; i < SK_ARRAY_COUNT(gPath); i++) {
SkASSERT(gPath[i].isConvex());

View File

@ -20,7 +20,7 @@
#include "include/core/SkImage.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPath.h"
#include "include/core/SkPathBuilder.h"
#include "include/core/SkPictureRecorder.h"
#include "include/core/SkRRect.h"
#include "include/core/SkString.h"
@ -62,6 +62,7 @@ DEF_MTNAME(SkMatrix)
DEF_MTNAME(SkRRect)
DEF_MTNAME(SkPath)
DEF_MTNAME(SkPaint)
DEF_MTNAME(SkPathBuilder)
DEF_MTNAME(SkPathEffect)
DEF_MTNAME(SkPicture)
DEF_MTNAME(SkPictureRecorder)
@ -530,7 +531,7 @@ static int lcanvas_drawPatch(lua_State* L) {
}
static int lcanvas_drawPath(lua_State* L) {
get_ref<SkCanvas>(L, 1)->drawPath(*get_obj<SkPath>(L, 2),
get_ref<SkCanvas>(L, 1)->drawPath(get_obj<SkPathBuilder>(L, 2)->snapshot(),
*get_obj<SkPaint>(L, 3));
return 0;
}
@ -879,19 +880,6 @@ static int lpaint_getPathEffect(lua_State* L) {
return 0;
}
static int lpaint_getFillPath(lua_State* L) {
const SkPaint* paint = get_obj<SkPaint>(L, 1);
const SkPath* path = get_obj<SkPath>(L, 2);
SkPath fillpath;
paint->getFillPath(*path, &fillpath);
SkLua lua(L);
lua.pushPath(fillpath);
return 1;
}
static int lpaint_gc(lua_State* L) {
get_obj<SkPaint>(L, 1)->~SkPaint();
return 0;
@ -923,7 +911,6 @@ static const struct luaL_Reg gSkPaint_Methods[] = {
{ "getShader", lpaint_getShader },
{ "setShader", lpaint_setShader },
{ "getPathEffect", lpaint_getPathEffect },
{ "getFillPath", lpaint_getFillPath },
{ "__gc", lpaint_gc },
{ nullptr, nullptr }
};
@ -1243,7 +1230,7 @@ static const struct luaL_Reg gSkMatrix_Methods[] = {
///////////////////////////////////////////////////////////////////////////////
static int lpath_getBounds(lua_State* L) {
SkLua(L).pushRect(get_obj<SkPath>(L, 1)->getBounds());
SkLua(L).pushRect(get_obj<SkPathBuilder>(L, 1)->computeBounds());
return 1;
}
@ -1262,7 +1249,7 @@ static const char* fill_type_to_str(SkPathFillType fill) {
}
static int lpath_getFillType(lua_State* L) {
SkPathFillType fill = get_obj<SkPath>(L, 1)->getFillType();
SkPathFillType fill = get_obj<SkPathBuilder>(L, 1)->fillType();
SkLua(L).pushString(fill_type_to_str(fill));
return 1;
}
@ -1303,25 +1290,25 @@ static SkString segment_masks_to_str(uint32_t segmentMasks) {
}
static int lpath_getSegmentTypes(lua_State* L) {
uint32_t segMasks = get_obj<SkPath>(L, 1)->getSegmentMasks();
uint32_t segMasks = get_obj<SkPathBuilder>(L, 1)->snapshot().getSegmentMasks();
SkLua(L).pushString(segment_masks_to_str(segMasks));
return 1;
}
static int lpath_isConvex(lua_State* L) {
bool isConvex = get_obj<SkPath>(L, 1)->isConvex();
bool isConvex = get_obj<SkPathBuilder>(L, 1)->snapshot().isConvex();
SkLua(L).pushBool(isConvex);
return 1;
}
static int lpath_isEmpty(lua_State* L) {
lua_pushboolean(L, get_obj<SkPath>(L, 1)->isEmpty());
lua_pushboolean(L, get_obj<SkPathBuilder>(L, 1)->snapshot().isEmpty());
return 1;
}
static int lpath_isRect(lua_State* L) {
SkRect r;
bool pred = get_obj<SkPath>(L, 1)->isRect(&r);
bool pred = get_obj<SkPathBuilder>(L, 1)->snapshot().isRect(&r);
int ret_count = 1;
lua_pushboolean(L, pred);
if (pred) {
@ -1332,13 +1319,13 @@ static int lpath_isRect(lua_State* L) {
}
static int lpath_countPoints(lua_State* L) {
lua_pushinteger(L, get_obj<SkPath>(L, 1)->countPoints());
lua_pushinteger(L, get_obj<SkPathBuilder>(L, 1)->snapshot().countPoints());
return 1;
}
static int lpath_getVerbs(lua_State* L) {
const SkPath* path = get_obj<SkPath>(L, 1);
SkPath::Iter iter(*path, false);
SkPath path = get_obj<SkPathBuilder>(L, 1)->snapshot();
SkPath::Iter iter(path, false);
SkPoint pts[4];
lua_newtable(L);
@ -1376,40 +1363,40 @@ static int lpath_getVerbs(lua_State* L) {
}
static int lpath_reset(lua_State* L) {
get_obj<SkPath>(L, 1)->reset();
get_obj<SkPathBuilder>(L, 1)->reset();
return 0;
}
static int lpath_moveTo(lua_State* L) {
get_obj<SkPath>(L, 1)->moveTo(lua2scalar(L, 2), lua2scalar(L, 3));
get_obj<SkPathBuilder>(L, 1)->moveTo(lua2scalar(L, 2), lua2scalar(L, 3));
return 0;
}
static int lpath_lineTo(lua_State* L) {
get_obj<SkPath>(L, 1)->lineTo(lua2scalar(L, 2), lua2scalar(L, 3));
get_obj<SkPathBuilder>(L, 1)->lineTo(lua2scalar(L, 2), lua2scalar(L, 3));
return 0;
}
static int lpath_quadTo(lua_State* L) {
get_obj<SkPath>(L, 1)->quadTo(lua2scalar(L, 2), lua2scalar(L, 3),
get_obj<SkPathBuilder>(L, 1)->quadTo(lua2scalar(L, 2), lua2scalar(L, 3),
lua2scalar(L, 4), lua2scalar(L, 5));
return 0;
}
static int lpath_cubicTo(lua_State* L) {
get_obj<SkPath>(L, 1)->cubicTo(lua2scalar(L, 2), lua2scalar(L, 3),
get_obj<SkPathBuilder>(L, 1)->cubicTo(lua2scalar(L, 2), lua2scalar(L, 3),
lua2scalar(L, 4), lua2scalar(L, 5),
lua2scalar(L, 6), lua2scalar(L, 7));
return 0;
}
static int lpath_close(lua_State* L) {
get_obj<SkPath>(L, 1)->close();
get_obj<SkPathBuilder>(L, 1)->close();
return 0;
}
static int lpath_gc(lua_State* L) {
get_obj<SkPath>(L, 1)->~SkPath();
get_obj<SkPathBuilder>(L, 1)->~SkPathBuilder();
return 0;
}
@ -1824,7 +1811,7 @@ static int lsk_newPaint(lua_State* L) {
}
static int lsk_newPath(lua_State* L) {
push_new<SkPath>(L);
push_new<SkPathBuilder>(L);
return 1;
}