Revert of Make AALinearizingConvexPathRenderer able to handle stroke and fill (patchset #7 id:120001 of https://codereview.chromium.org/2301353004/ )

Reason for revert:
Image quality issues on Android devices

Original issue's description:
> Make AALinearizingConvexPathRenderer able to handle stroke and fill
>
> This is intended to catch stroke-and-fill convex paths with potentially small stroke widths (e.g., .1).
>
> It does have the disconcerting side effect of changing bevel-joined stroke-and-filled degenerate-single-line-rects into plain rects (w/o triangular end-caps).
>
> GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2301353004
>
> Committed: https://skia.googlesource.com/skia/+/522bcd99fa65a8abd130880f59b500cf367d0845

TBR=ethannicholas@google.com,jvanverth@google.com
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true

Review-Url: https://codereview.chromium.org/2318183002
This commit is contained in:
robertphillips 2016-09-07 08:29:08 -07:00 committed by Commit bot
parent b393a49e5f
commit 7a00e8bc98
3 changed files with 24 additions and 115 deletions

View File

@ -32,17 +32,11 @@ static const SkScalar kRoundCapThreshold = 0.8f;
// dot product above which we consider two adjacent curves to be part of the "same" curve
static const SkScalar kCurveConnectionThreshold = 0.8f;
static bool intersect(const SkPoint& p0, const SkPoint& n0,
const SkPoint& p1, const SkPoint& n1,
SkScalar* t) {
static SkScalar intersect(const SkPoint& p0, const SkPoint& n0,
const SkPoint& p1, const SkPoint& n1) {
const SkPoint v = p1 - p0;
SkScalar perpDot = n0.fX * n1.fY - n0.fY * n1.fX;
if (SkScalarNearlyZero(perpDot)) {
return false;
}
*t = (v.fX * n1.fY - v.fY * n1.fX) / perpDot;
SkASSERT(SkScalarIsFinite(*t));
return true;
return (v.fX * n1.fY - v.fY * n1.fX) / perpDot;
}
// This is a special case version of intersect where we have the vector
@ -224,44 +218,7 @@ bool GrAAConvexTessellator::tessellate(const SkMatrix& m, const SkPath& path) {
SkScalar coverage = 1.0f;
SkScalar scaleFactor = 0.0f;
if (SkStrokeRec::kStrokeAndFill_Style == fStyle) {
SkASSERT(m.isSimilarity());
scaleFactor = m.getMaxScale(); // x and y scale are the same
SkScalar effectiveStrokeWidth = scaleFactor * fStrokeWidth;
Ring outerStrokeAndAARing;
this->createOuterRing(fInitialRing,
effectiveStrokeWidth / 2 + kAntialiasingRadius, 0.0,
&outerStrokeAndAARing);
// discard all the triangles added between the originating ring and the new outer ring
fIndices.rewind();
outerStrokeAndAARing.init(*this);
outerStrokeAndAARing.makeOriginalRing();
// Add the outer stroke ring's normals to the originating ring's normals
// so it can also act as an originating ring
fNorms.setReserve(fNorms.count() + outerStrokeAndAARing.numPts());
for (int i = 0; i < outerStrokeAndAARing.numPts(); ++i) {
fNorms.push(outerStrokeAndAARing.norm(i));
}
// the bisectors are only needed for the computation of the outer ring
fBisectors.rewind();
Ring* insetAARing;
this->createInsetRings(outerStrokeAndAARing,
0.0f, 0.0f, 2*kAntialiasingRadius, 1.0f,
&insetAARing);
SkDEBUGCODE(this->validate();)
return true;
}
if (SkStrokeRec::kStroke_Style == fStyle) {
SkASSERT(fStrokeWidth >= 0.0f);
if (fStrokeWidth >= 0.0f) {
SkASSERT(m.isSimilarity());
scaleFactor = m.getMaxScale(); // x and y scale are the same
SkScalar effectiveStrokeWidth = scaleFactor * fStrokeWidth;
@ -278,16 +235,15 @@ bool GrAAConvexTessellator::tessellate(const SkMatrix& m, const SkPath& path) {
// the bisectors are only needed for the computation of the outer ring
fBisectors.rewind();
if (SkStrokeRec::kStroke_Style == fStyle && fInitialRing.numPts() > 2) {
SkASSERT(fStrokeWidth >= 0.0f);
if (fStrokeWidth >= 0.0f && fInitialRing.numPts() > 2) {
SkScalar effectiveStrokeWidth = scaleFactor * fStrokeWidth;
Ring* insetStrokeRing;
SkScalar strokeDepth = effectiveStrokeWidth / 2 - kAntialiasingRadius;
if (this->createInsetRings(fInitialRing, 0.0f, coverage, strokeDepth, coverage,
&insetStrokeRing)) {
&insetStrokeRing)) {
Ring* insetAARing;
this->createInsetRings(*insetStrokeRing, strokeDepth, coverage, strokeDepth +
kAntialiasingRadius * 2, 0.0f, &insetAARing);
kAntialiasingRadius * 2, 0.0f, &insetAARing);
}
} else {
Ring* insetAARing;
@ -434,7 +390,7 @@ bool GrAAConvexTessellator::extractFromPath(const SkMatrix& m, const SkPath& pat
this->computeBisectors();
} else if (this->numPts() == 2) {
// We've got two points, so we're degenerate.
if (fStyle == SkStrokeRec::kFill_Style) {
if (fStrokeWidth < 0.0f) {
// it's a fill, so we don't need to worry about degenerate paths
return false;
}
@ -630,7 +586,7 @@ void GrAAConvexTessellator::createOuterRing(const Ring& previousRing, SkScalar o
// Something went wrong in the creation of the next ring. If we're filling the shape, just go ahead
// and fan it.
void GrAAConvexTessellator::terminate(const Ring& ring) {
if (fStyle != SkStrokeRec::kStroke_Style) {
if (fStrokeWidth < 0.0f) {
this->fanRing(ring);
}
}
@ -660,14 +616,8 @@ bool GrAAConvexTessellator::createInsetRing(const Ring& lastRing, Ring* nextRing
for (int cur = 0; cur < lastRing.numPts(); ++cur) {
int next = (cur + 1) % lastRing.numPts();
SkScalar t;
bool result = intersect(this->point(lastRing.index(cur)), lastRing.bisector(cur),
this->point(lastRing.index(next)), lastRing.bisector(next),
&t);
if (!result) {
continue;
}
SkScalar t = intersect(this->point(lastRing.index(cur)), lastRing.bisector(cur),
this->point(lastRing.index(next)), lastRing.bisector(next));
SkScalar dist = -t * lastRing.norm(cur).dot(lastRing.bisector(cur));
if (minDist > dist) {
@ -795,8 +745,8 @@ bool GrAAConvexTessellator::createInsetRing(const Ring& lastRing, Ring* nextRing
this->addTri(lastRing.index(i), dst[next], dst[i]);
}
if (done && fStyle != SkStrokeRec::kStroke_Style) {
// fill or stroke-and-fill
if (done && fStrokeWidth < 0.0f) {
// fill
this->fanRing(*nextRing);
}
@ -910,7 +860,7 @@ void GrAAConvexTessellator::lineTo(SkPoint p, CurveState curve) {
return;
}
}
SkScalar initialRingCoverage = (SkStrokeRec::kFill_Style == fStyle) ? 0.5f : 1.0f;
SkScalar initialRingCoverage = fStrokeWidth < 0.0f ? 0.5f : 1.0f;
this->addPt(p, 0.0f, initialRingCoverage, false, curve);
if (this->numPts() > 1) {
*fNorms.push() = fPts.top() - fPts[fPts.count()-2];

View File

@ -12,7 +12,6 @@
#include "SkPaint.h"
#include "SkPoint.h"
#include "SkScalar.h"
#include "SkStrokeRec.h"
#include "SkTDArray.h"
class SkCanvas;
@ -32,13 +31,11 @@ class GrAAConvexTessellator;
// computeDepthFromEdge requests.
class GrAAConvexTessellator {
public:
GrAAConvexTessellator(SkStrokeRec::Style style = SkStrokeRec::kFill_Style,
SkScalar strokeWidth = -1.0f,
GrAAConvexTessellator(SkScalar strokeWidth = -1.0f,
SkPaint::Join join = SkPaint::Join::kBevel_Join,
SkScalar miterLimit = 0.0f)
: fSide(SkPoint::kOn_Side)
, fStrokeWidth(strokeWidth)
, fStyle(style)
, fJoin(join)
, fMiterLimit(miterLimit) {
}
@ -139,13 +136,6 @@ private:
pt->fOrigEdgeId = origEdgeId;
}
// Upgrade this ring so that it can behave like an originating ring
void makeOriginalRing() {
for (int i = 0; i < fPts.count(); ++i) {
fPts[i].fOrigEdgeId = fPts[i].fIndex;
}
}
// init should be called after all the indices have been added (via addIdx)
void init(const GrAAConvexTessellator& tess);
void init(const SkTDArray<SkVector>& norms, const SkTDArray<SkVector>& bisectors);
@ -277,9 +267,8 @@ private:
#endif
CandidateVerts fCandidateVerts;
// the stroke width is only used for stroke or stroke-and-fill styles
// < 0 means filling rather than stroking
SkScalar fStrokeWidth;
SkStrokeRec::Style fStyle;
SkPaint::Join fJoin;

View File

@ -50,17 +50,12 @@ bool GrAALinearizingConvexPathRenderer::onCanDrawPath(const CanDrawPathArgs& arg
return false;
}
const SkStrokeRec& stroke = args.fShape->style().strokeRec();
if (stroke.getStyle() == SkStrokeRec::kStroke_Style ||
stroke.getStyle() == SkStrokeRec::kStrokeAndFill_Style) {
if (stroke.getStyle() == SkStrokeRec::kStroke_Style) {
if (!args.fViewMatrix->isSimilarity()) {
return false;
}
SkScalar strokeWidth = args.fViewMatrix->getMaxScale() * stroke.getWidth();
if (strokeWidth < 1.0f && stroke.getStyle() == SkStrokeRec::kStroke_Style) {
return false;
}
return strokeWidth <= kMaxStrokeWidth &&
return strokeWidth >= 1.0f && strokeWidth <= kMaxStrokeWidth &&
args.fShape->knownToBeClosed() &&
stroke.getJoin() != SkPaint::Join::kRound_Join;
}
@ -131,11 +126,9 @@ public:
const SkMatrix& viewMatrix,
const SkPath& path,
SkScalar strokeWidth,
SkStrokeRec::Style style,
SkPaint::Join join,
SkScalar miterLimit) : INHERITED(ClassID()) {
fGeoData.emplace_back(Geometry{ color, viewMatrix, path,
strokeWidth, style, join, miterLimit });
fGeoData.emplace_back(Geometry{color, viewMatrix, path, strokeWidth, join, miterLimit});
// compute bounds
SkRect bounds = path.getBounds();
@ -236,8 +229,7 @@ private:
uint16_t* indices = (uint16_t*) sk_malloc_throw(maxIndices * sizeof(uint16_t));
for (int i = 0; i < instanceCount; i++) {
const Geometry& args = fGeoData[i];
GrAAConvexTessellator tess(args.fStyle, args.fStrokeWidth,
args.fJoin, args.fMiterLimit);
GrAAConvexTessellator tess(args.fStrokeWidth, args.fJoin, args.fMiterLimit);
if (!tess.tessellate(args.fViewMatrix, args.fPath)) {
continue;
@ -317,7 +309,6 @@ private:
SkMatrix fViewMatrix;
SkPath fPath;
SkScalar fStrokeWidth;
SkStrokeRec::Style fStyle;
SkPaint::Join fJoin;
SkScalar fMiterLimit;
};
@ -333,7 +324,6 @@ bool GrAALinearizingConvexPathRenderer::onDrawPath(const DrawPathArgs& args) {
"GrAALinearizingConvexPathRenderer::onDrawPath");
SkASSERT(!args.fDrawContext->isUnifiedMultisampled());
SkASSERT(!args.fShape->isEmpty());
SkASSERT(!args.fShape->style().pathEffect());
SkPath path;
args.fShape->asPath(&path);
@ -345,9 +335,8 @@ bool GrAALinearizingConvexPathRenderer::onDrawPath(const DrawPathArgs& args) {
SkAutoTUnref<GrDrawBatch> batch(new AAFlatteningConvexPathBatch(args.fPaint->getColor(),
*args.fViewMatrix,
path, strokeWidth,
stroke.getStyle(),
join, miterLimit));
path, strokeWidth, join,
miterLimit));
GrPipelineBuilder pipelineBuilder(*args.fPaint);
pipelineBuilder.setUserStencil(args.fUserStencilSettings);
@ -365,29 +354,10 @@ DRAW_BATCH_TEST_DEFINE(AAFlatteningConvexPathBatch) {
GrColor color = GrRandomColor(random);
SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random);
SkPath path = GrTest::TestPathConvex(random);
SkStrokeRec::Style styles[3] = { SkStrokeRec::kFill_Style,
SkStrokeRec::kStroke_Style,
SkStrokeRec::kStrokeAndFill_Style };
SkStrokeRec::Style style = styles[random->nextU() % 3];
SkScalar strokeWidth = -1.f;
SkScalar strokeWidth = random->nextBool() ? -1.f : 2.f;
SkPaint::Join join = SkPaint::kMiter_Join;
SkScalar miterLimit = 0.5f;
if (SkStrokeRec::kFill_Style != style) {
strokeWidth = random->nextRangeF(1.0f, 10.0f);
if (random->nextBool()) {
join = SkPaint::kMiter_Join;
} else {
join = SkPaint::kBevel_Join;
}
miterLimit = random->nextRangeF(0.5f, 2.0f);
}
return new AAFlatteningConvexPathBatch(color, viewMatrix, path, strokeWidth,
style, join, miterLimit);
return new AAFlatteningConvexPathBatch(color, viewMatrix, path, strokeWidth, join, miterLimit);
}
#endif