aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/core/SkRRect.h2
-rw-r--r--samplecode/SampleAndroidShadows.cpp3
-rw-r--r--src/core/SkRRect.cpp10
-rw-r--r--src/effects/shadows/SkAmbientShadowMaskFilter.cpp5
-rw-r--r--src/effects/shadows/SkSpotShadowMaskFilter.cpp42
-rw-r--r--src/utils/SkShadowUtils.cpp24
6 files changed, 55 insertions, 31 deletions
diff --git a/include/core/SkRRect.h b/include/core/SkRRect.h
index 3b691aab1b..4b7a33e43f 100644
--- a/include/core/SkRRect.h
+++ b/include/core/SkRRect.h
@@ -110,7 +110,7 @@ public:
inline bool isNinePatch() const { return kNinePatch_Type == this->getType(); }
inline bool isComplex() const { return kComplex_Type == this->getType(); }
- bool allCornersCircular() const;
+ bool allCornersCircular(SkScalar tolerance = SK_ScalarNearlyZero) const;
SkScalar width() const { return fRect.width(); }
SkScalar height() const { return fRect.height(); }
diff --git a/samplecode/SampleAndroidShadows.cpp b/samplecode/SampleAndroidShadows.cpp
index 0c0baaba10..55acd57f09 100644
--- a/samplecode/SampleAndroidShadows.cpp
+++ b/samplecode/SampleAndroidShadows.cpp
@@ -473,6 +473,7 @@ protected:
paint.setAntiAlias(true);
SkPoint3 lightPos = fLightPos;
+ lightPos.fX = canvas->getBaseLayerSize().fWidth * 0.5f;
paint.setColor(SK_ColorWHITE);
canvas->translate(200, 90);
@@ -496,7 +497,7 @@ protected:
canvas->translate(-250, 110);
lightPos.fX -= 250;
lightPos.fY += 110;
- zValue = SkTMax(1.0f, 8 + fZDelta);
+ zValue = SkTMax(1.0f, 12 + fZDelta);
zFunc = [zValue](SkScalar, SkScalar) { return zValue; };
this->drawShadowedPath(canvas, fCirclePath, zFunc, paint, kAmbientAlpha,
lightPos, kLightWidth, 0.5f);
diff --git a/src/core/SkRRect.cpp b/src/core/SkRRect.cpp
index 824ee62e60..8d69f4afc6 100644
--- a/src/core/SkRRect.cpp
+++ b/src/core/SkRRect.cpp
@@ -251,11 +251,11 @@ bool SkRRect::checkCornerContainment(SkScalar x, SkScalar y) const {
return dist <= SkScalarSquare(fRadii[index].fX * fRadii[index].fY);
}
-bool SkRRect::allCornersCircular() const {
- return fRadii[0].fX == fRadii[0].fY &&
- fRadii[1].fX == fRadii[1].fY &&
- fRadii[2].fX == fRadii[2].fY &&
- fRadii[3].fX == fRadii[3].fY;
+bool SkRRect::allCornersCircular(SkScalar tolerance) const {
+ return SkScalarNearlyEqual(fRadii[0].fX, fRadii[0].fY, tolerance) &&
+ SkScalarNearlyEqual(fRadii[1].fX, fRadii[1].fY, tolerance) &&
+ SkScalarNearlyEqual(fRadii[2].fX, fRadii[2].fY, tolerance) &&
+ SkScalarNearlyEqual(fRadii[3].fX, fRadii[3].fY, tolerance);
}
bool SkRRect::contains(const SkRect& rect) const {
diff --git a/src/effects/shadows/SkAmbientShadowMaskFilter.cpp b/src/effects/shadows/SkAmbientShadowMaskFilter.cpp
index e6a8de4141..84f9836b52 100644
--- a/src/effects/shadows/SkAmbientShadowMaskFilter.cpp
+++ b/src/effects/shadows/SkAmbientShadowMaskFilter.cpp
@@ -163,9 +163,8 @@ bool SkAmbientShadowMaskFilterImpl::directFilterMaskGPU(GrContext* context,
}
// if circle
- // TODO: switch to SkScalarNearlyEqual when either oval renderer is updated or we
- // have our own GeometryProc.
- if (path.isOval(nullptr) && path.getBounds().width() == path.getBounds().height()) {
+ if (path.isOval(nullptr) && SkScalarNearlyEqual(path.getBounds().width(),
+ path.getBounds().height())) {
SkRRect rrect = SkRRect::MakeOval(path.getBounds());
return this->directFilterRRectMaskGPU(context, rtContext, std::move(paint), clip,
SkMatrix::I(), strokeRec, rrect, rrect);
diff --git a/src/effects/shadows/SkSpotShadowMaskFilter.cpp b/src/effects/shadows/SkSpotShadowMaskFilter.cpp
index ee82342ecc..93c7e9c0fa 100644
--- a/src/effects/shadows/SkSpotShadowMaskFilter.cpp
+++ b/src/effects/shadows/SkSpotShadowMaskFilter.cpp
@@ -180,9 +180,8 @@ bool SkSpotShadowMaskFilterImpl::directFilterMaskGPU(GrContext* context,
}
// if circle
- // TODO: switch to SkScalarNearlyEqual when either oval renderer is updated or we
- // have our own GeometryProc.
- if (path.isOval(nullptr) && path.getBounds().width() == path.getBounds().height()) {
+ if (path.isOval(nullptr) && SkScalarNearlyEqual(path.getBounds().width(),
+ path.getBounds().height())) {
SkRRect rrect = SkRRect::MakeOval(path.getBounds());
return this->directFilterRRectMaskGPU(context, rtContext, std::move(paint), clip,
SkMatrix::I(), strokeRec, rrect, rrect);
@@ -211,7 +210,7 @@ bool SkSpotShadowMaskFilterImpl::directFilterRRectMaskGPU(GrContext*,
if (SkStrokeRec::kFill_Style != strokeRec.getStyle()) {
return false;
}
- // Fast path only supports simple rrects with circular corners.
+ // Fast path only supports simple rrects with near-circular corners.
SkASSERT(devRRect.allCornersCircular());
if (!rrect.isRect() && !rrect.isOval() && !rrect.isSimple()) {
return false;
@@ -236,7 +235,9 @@ bool SkSpotShadowMaskFilterImpl::directFilterRRectMaskGPU(GrContext*,
if (fSpotAlpha > 0.0f) {
float zRatio = SkTPin(fOccluderHeight / (fLightPos.fZ - fOccluderHeight), 0.0f, 0.95f);
- SkScalar srcSpaceSpotRadius = 2.0f * fLightRadius * zRatio;
+ SkScalar devSpaceSpotRadius = 2.0f * fLightRadius * zRatio;
+ // handle scale of radius and pad due to CTM
+ const SkScalar srcSpaceSpotRadius = devSpaceSpotRadius / scaleFactor;
SkRRect spotRRect;
if (isRect) {
@@ -250,18 +251,18 @@ bool SkSpotShadowMaskFilterImpl::directFilterRRectMaskGPU(GrContext*,
const SkScalar scale = fLightPos.fZ / (fLightPos.fZ - fOccluderHeight);
spotRRect.transform(SkMatrix::MakeScale(scale, scale), &spotShadowRRect);
- SkPoint center = SkPoint::Make(spotShadowRRect.rect().centerX(),
- spotShadowRRect.rect().centerY());
+ SkPoint spotOffset = SkPoint::Make(zRatio*(-fLightPos.fX), zRatio*(-fLightPos.fY));
+ // Adjust for the effect of the scale.
+ spotOffset.fX += scale*viewMatrix[SkMatrix::kMTransX];
+ spotOffset.fY += scale*viewMatrix[SkMatrix::kMTransY];
+ // This offset is in dev space, need to transform it into source space.
SkMatrix ctmInverse;
if (!viewMatrix.invert(&ctmInverse)) {
SkDebugf("Matrix is degenerate. Will not render spot shadow!\n");
//**** TODO: this is not good
return true;
}
- SkPoint lightPos2D = SkPoint::Make(fLightPos.fX, fLightPos.fY);
- ctmInverse.mapPoints(&lightPos2D, 1);
- const SkPoint spotOffset = SkPoint::Make(zRatio*(center.fX - lightPos2D.fX),
- zRatio*(center.fY - lightPos2D.fY));
+ ctmInverse.mapPoints(&spotOffset, 1);
// We want to extend the stroked area in so that it meets up with the caster
// geometry. The stroked geometry will, by definition already be inset half the
@@ -292,17 +293,20 @@ bool SkSpotShadowMaskFilterImpl::directFilterRRectMaskGPU(GrContext*,
} else {
// Since we can't have unequal strokes, inset the shadow rect so the inner
// and outer edges of the stroke will land where we want.
- SkRect insetRect = spotShadowRRect.rect().makeInset(insetAmount / 2.0f,
- insetAmount / 2.0f);
- SkScalar insetRad = SkTMax(spotShadowRRect.getSimpleRadii().fX - insetAmount / 2.0f,
- minRadius);
- spotShadowRRect = SkRRect::MakeRectXY(insetRect, insetRad, insetRad);
+ insetAmount *= 0.5f;
+ SkRect insetRect = spotShadowRRect.rect().makeInset(insetAmount, insetAmount);
+ // If the shadowRRect was an oval then its inset will also be one.
+ // We set it explicitly to avoid errors.
+ if (spotShadowRRect.isOval()) {
+ spotShadowRRect = SkRRect::MakeOval(insetRect);
+ } else {
+ SkScalar insetRad = SkTMax(spotShadowRRect.getSimpleRadii().fX - insetAmount,
+ minRadius);
+ spotShadowRRect = SkRRect::MakeRectXY(insetRect, insetRad, insetRad);
+ }
spotStrokeRec.setStrokeStyle(strokeWidth, false);
}
- // handle scale of radius and pad due to CTM
- const SkScalar devSpaceSpotRadius = srcSpaceSpotRadius * scaleFactor;
-
spotShadowRRect.offset(spotOffset.fX, spotOffset.fY);
rtContext->drawShadowRRect(clip, std::move(paint), viewMatrix, spotShadowRRect,
diff --git a/src/utils/SkShadowUtils.cpp b/src/utils/SkShadowUtils.cpp
index 2e560b454e..8206bd3f54 100644
--- a/src/utils/SkShadowUtils.cpp
+++ b/src/utils/SkShadowUtils.cpp
@@ -471,12 +471,12 @@ void SkShadowUtils::DrawShadow(SkCanvas* canvas, const SkPath& path, SkScalar oc
if (ambientAlpha > 0) {
newPaint.setMaskFilter(SkAmbientShadowMaskFilter::Make(occluderHeight, ambientAlpha,
flags));
- canvas->drawPath(path, newPaint);
+ canvas->drawOval(rect, newPaint);
}
if (spotAlpha > 0) {
newPaint.setMaskFilter(SkSpotShadowMaskFilter::Make(occluderHeight, devLightPos,
lightRadius, spotAlpha, flags));
- canvas->drawPath(path, newPaint);
+ canvas->drawOval(rect, newPaint);
}
return;
}
@@ -565,6 +565,26 @@ void SkShadowUtils::DrawUncachedShadow(SkCanvas* canvas, const SkPath& path,
uint32_t flags) {
SkAutoCanvasRestore acr(canvas, true);
SkMatrix viewMatrix = canvas->getTotalMatrix();
+
+ // try circular fast path
+ SkRect rect;
+ if (viewMatrix.isSimilarity() &&
+ path.isOval(&rect) && rect.width() == rect.height()) {
+ SkPaint newPaint;
+ newPaint.setColor(color);
+ if (ambientAlpha > 0) {
+ newPaint.setMaskFilter(SkAmbientShadowMaskFilter::Make(heightFunc(0,0), ambientAlpha,
+ flags));
+ canvas->drawOval(rect, newPaint);
+ }
+ if (spotAlpha > 0) {
+ newPaint.setMaskFilter(SkSpotShadowMaskFilter::Make(heightFunc(0,0), lightPos,
+ lightRadius, spotAlpha, flags));
+ canvas->drawOval(rect, newPaint);
+ }
+ return;
+ }
+
canvas->resetMatrix();
bool transparent = SkToBool(flags & SkShadowFlags::kTransparentOccluder_ShadowFlag);