Revert "Revert "Fix rendering of drrects with small circular inner rrects.""
This reverts commit ec727c981d
.
Change-Id: Id3164619016d58b2bcc0b8af606215653f553fce
Reviewed-on: https://skia-review.googlesource.com/79422
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
This commit is contained in:
parent
80654c16bd
commit
6574921253
42
gm/drrect_small_inner.cpp
Normal file
42
gm/drrect_small_inner.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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 "SkCanvas.h"
|
||||
#include "SkPaint.h"
|
||||
#include "SkRRect.h"
|
||||
#include "gm.h"
|
||||
|
||||
DEF_SIMPLE_GM(drrect_small_inner, canvas, 170, 610) {
|
||||
SkPaint paint;
|
||||
paint.setAntiAlias(true);
|
||||
static constexpr SkScalar kOuterRadius = 35.f;
|
||||
auto outer = SkRRect::MakeOval(SkRect::MakeXYWH(0, 0, 2 * kOuterRadius, 2 * kOuterRadius));
|
||||
canvas->translate(10.f, 10.f);
|
||||
canvas->save();
|
||||
for (bool offcenter : {false, true}) {
|
||||
for (bool oval : {false, true}) {
|
||||
for (SkScalar innerRadiusX : {1.f, 0.5f, 0.1f, .01f}) {
|
||||
SkScalar innerRadiusY = innerRadiusX;
|
||||
if (oval) {
|
||||
innerRadiusY *= 0.95f;
|
||||
}
|
||||
SkScalar tx = kOuterRadius - innerRadiusX;
|
||||
SkScalar ty = kOuterRadius - innerRadiusY;
|
||||
if (offcenter) {
|
||||
tx += 1.f;
|
||||
}
|
||||
auto inner = SkRRect::MakeOval(
|
||||
SkRect::MakeXYWH(tx, ty, 2 * innerRadiusX, 2 * innerRadiusY));
|
||||
canvas->drawDRRect(outer, inner, paint);
|
||||
canvas->translate(0, 2 * kOuterRadius + 5);
|
||||
}
|
||||
}
|
||||
canvas->restore();
|
||||
canvas->translate(2 * kOuterRadius + 2, 0);
|
||||
}
|
||||
canvas->restore();
|
||||
}
|
@ -118,6 +118,7 @@ gm_sources = [
|
||||
"$_gm/drawregionmodes.cpp",
|
||||
"$_gm/dropshadowimagefilter.cpp",
|
||||
"$_gm/drrect.cpp",
|
||||
"$_gm/drrect_small_inner.cpp",
|
||||
"$_gm/dstreadshuffle.cpp",
|
||||
"$_gm/emboss.cpp",
|
||||
"$_gm/emptypath.cpp",
|
||||
|
@ -1224,6 +1224,28 @@ bool GrRenderTargetContext::drawFilledDRRect(const GrClip& clip,
|
||||
}
|
||||
}
|
||||
|
||||
SkTCopyOnFirstWrite<SkRRect> inner(origInner), outer(origOuter);
|
||||
|
||||
if (aa == GrAA::kYes && inner->isCircle() && outer->isCircle()) {
|
||||
auto outerR = outer->width() / 2.f;
|
||||
auto innerR = inner->width() / 2.f;
|
||||
auto cx = outer->getBounds().fLeft + outerR;
|
||||
auto cy = outer->getBounds().fTop + outerR;
|
||||
if (SkScalarNearlyEqual(cx, inner->getBounds().fLeft + innerR) &&
|
||||
SkScalarNearlyEqual(cy, inner->getBounds().fTop + innerR)) {
|
||||
auto avgR = (innerR + outerR) / 2.f;
|
||||
auto circleBounds = SkRect::MakeLTRB(cx - avgR, cy - avgR, cx + avgR, cy + avgR);
|
||||
SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
|
||||
stroke.setStrokeStyle(outerR - innerR);
|
||||
auto op = GrOvalOpFactory::MakeOvalOp(std::move(paint), viewMatrix, circleBounds,
|
||||
stroke, this->caps()->shaderCaps());
|
||||
if (op) {
|
||||
this->addDrawOp(clip, std::move(op));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
|
||||
|
||||
GrClipEdgeType innerEdgeType, outerEdgeType;
|
||||
@ -1235,7 +1257,6 @@ bool GrRenderTargetContext::drawFilledDRRect(const GrClip& clip,
|
||||
outerEdgeType = GrClipEdgeType::kFillBW;
|
||||
}
|
||||
|
||||
SkTCopyOnFirstWrite<SkRRect> inner(origInner), outer(origOuter);
|
||||
SkMatrix inverseVM;
|
||||
if (!viewMatrix.isIdentity()) {
|
||||
if (!origInner.transform(viewMatrix, inner.writable())) {
|
||||
|
@ -66,6 +66,9 @@ private:
|
||||
SkScalar effectiveRadius = radius;
|
||||
if (GrProcessorEdgeTypeIsInverseFill((GrClipEdgeType)edgeType)) {
|
||||
effectiveRadius -= 0.5f;
|
||||
// When the radius is 0.5 effectiveRadius is 0 which causes an inf * 0 in the
|
||||
// shader.
|
||||
effectiveRadius = SkTMax(0.001f, effectiveRadius);
|
||||
} else {
|
||||
effectiveRadius += 0.5f;
|
||||
}
|
||||
@ -108,7 +111,7 @@ std::unique_ptr<GrFragmentProcessor> GrCircleEffect::TestCreate(GrProcessorTestD
|
||||
SkPoint center;
|
||||
center.fX = testData->fRandom->nextRangeScalar(0.f, 1000.f);
|
||||
center.fY = testData->fRandom->nextRangeScalar(0.f, 1000.f);
|
||||
SkScalar radius = testData->fRandom->nextRangeF(0.f, 1000.f);
|
||||
SkScalar radius = testData->fRandom->nextRangeF(1.f, 1000.f);
|
||||
GrClipEdgeType et;
|
||||
do {
|
||||
et = (GrClipEdgeType)testData->fRandom->nextULessThan(kGrClipEdgeTypeCnt);
|
||||
|
@ -15,6 +15,18 @@ half prevRadius = -1;
|
||||
// fills and (..., radius - 0.5, 1 / (radius - 0.5)) for inverse fills.
|
||||
uniform half4 circle;
|
||||
|
||||
@make {
|
||||
static std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType edgeType, SkPoint center,
|
||||
float radius) {
|
||||
// A radius below half causes the implicit insetting done by this processor to become
|
||||
// inverted. We could handle this case by making the processor code more complicated.
|
||||
if (radius < .5f) {
|
||||
return nullptr;
|
||||
}
|
||||
return std::unique_ptr<GrFragmentProcessor>(new GrCircleEffect(edgeType, center, radius));
|
||||
}
|
||||
}
|
||||
|
||||
@optimizationFlags { kCompatibleWithCoverageAsAlpha_OptimizationFlag }
|
||||
|
||||
@setData(pdman) {
|
||||
@ -22,6 +34,8 @@ uniform half4 circle;
|
||||
SkScalar effectiveRadius = radius;
|
||||
if (GrProcessorEdgeTypeIsInverseFill((GrClipEdgeType) edgeType)) {
|
||||
effectiveRadius -= 0.5f;
|
||||
// When the radius is 0.5 effectiveRadius is 0 which causes an inf * 0 in the shader.
|
||||
effectiveRadius = SkTMax(0.001f, effectiveRadius);
|
||||
} else {
|
||||
effectiveRadius += 0.5f;
|
||||
}
|
||||
@ -58,7 +72,7 @@ void main() {
|
||||
SkPoint center;
|
||||
center.fX = testData->fRandom->nextRangeScalar(0.f, 1000.f);
|
||||
center.fY = testData->fRandom->nextRangeScalar(0.f, 1000.f);
|
||||
SkScalar radius = testData->fRandom->nextRangeF(0.f, 1000.f);
|
||||
SkScalar radius = testData->fRandom->nextRangeF(1.f, 1000.f);
|
||||
GrClipEdgeType et;
|
||||
do {
|
||||
et = (GrClipEdgeType) testData->fRandom->nextULessThan(kGrClipEdgeTypeCnt);
|
||||
|
@ -19,8 +19,14 @@ public:
|
||||
GrClipEdgeType edgeType() const { return fEdgeType; }
|
||||
SkPoint center() const { return fCenter; }
|
||||
float radius() const { return fRadius; }
|
||||
|
||||
static std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType edgeType, SkPoint center,
|
||||
float radius) {
|
||||
// A radius below half causes the implicit insetting done by this processor to become
|
||||
// inverted. We could handle this case by making the processor code more complicated.
|
||||
if (radius < .5f) {
|
||||
return nullptr;
|
||||
}
|
||||
return std::unique_ptr<GrFragmentProcessor>(new GrCircleEffect(edgeType, center, radius));
|
||||
}
|
||||
GrCircleEffect(const GrCircleEffect& src);
|
||||
|
Loading…
Reference in New Issue
Block a user