aboutsummaryrefslogtreecommitdiffhomepage
path: root/samplecode/SampleAndroidShadows.cpp
diff options
context:
space:
mode:
authorGravatar jvanverth <jvanverth@google.com>2016-08-29 07:17:47 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-08-29 07:17:47 -0700
commita4f1af8f9778462184c2bef91de1b1827568c08b (patch)
tree15431f3725abb5c2d3ed87b345736c66d382c276 /samplecode/SampleAndroidShadows.cpp
parenta28e263d42760370c9ff0b269b31a78d6701fb44 (diff)
Use stroked rrects for Android shadow sample
Changes the Android shadow sample to use stroked roundrects when we can (mainly if stroked geometry area < fill geometry area). Also changes the setup for the overstroke geometry so that it computes the correct distance to the outer edge. GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2283003003 Review-Url: https://codereview.chromium.org/2283003003
Diffstat (limited to 'samplecode/SampleAndroidShadows.cpp')
-rwxr-xr-xsamplecode/SampleAndroidShadows.cpp100
1 files changed, 60 insertions, 40 deletions
diff --git a/samplecode/SampleAndroidShadows.cpp b/samplecode/SampleAndroidShadows.cpp
index c7a2f63db1..f411e5c9b3 100755
--- a/samplecode/SampleAndroidShadows.cpp
+++ b/samplecode/SampleAndroidShadows.cpp
@@ -143,44 +143,46 @@ protected:
return;
}
- SkRect pathRect;
- SkRRect pathRRect;
- if ((!path.isOval(&pathRect) || pathRect.width() != pathRect.height()) &&
- (!path.isRRect(&pathRRect) || !pathRRect.allCornersCircular()) &&
- !path.isRect(&pathRect)) {
- this->drawAmbientShadow(canvas, path, zValue, ambientAlpha);
- return;
- }
-
const SkScalar kHeightFactor = 1.f / 128.f;
const SkScalar kGeomFactor = 64;
SkScalar umbraAlpha = 1 / (1 + SkMaxScalar(zValue*kHeightFactor, 0));
SkScalar radius = zValue*kHeightFactor*kGeomFactor;
- // For all of these, we outset the rect by the radius to get our coverage shape.
+ SkRect pathRect;
+ SkRRect pathRRect;
+ if (radius >= 64 ||
+ !((path.isOval(&pathRect) && pathRect.width() == pathRect.height()) ||
+ (path.isRRect(&pathRRect) && pathRRect.allCornersCircular()) ||
+ path.isRect(&pathRect))) {
+ this->drawAmbientShadow(canvas, path, zValue, ambientAlpha);
+ return;
+ }
+
+ // For all of these, we outset the rect by half the radius to get our stroke shape.
+ SkScalar halfRadius = SK_ScalarHalf*radius;
if (path.isOval(nullptr)) {
- pathRect.outset(radius, radius);
+ pathRect.outset(halfRadius, halfRadius);
pathRRect = SkRRect::MakeOval(pathRect);
} else if (path.isRect(nullptr)) {
- pathRect.outset(radius, radius);
- pathRRect = SkRRect::MakeRectXY(pathRect, radius, radius);
+ pathRect.outset(halfRadius, halfRadius);
+ pathRRect = SkRRect::MakeRectXY(pathRect, halfRadius, halfRadius);
} else {
- pathRRect.outset(radius, radius);
+ pathRRect.outset(halfRadius, halfRadius);
}
SkPaint paint;
paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kStroke_Style);
+ // we outset the stroke a little to cover up AA on the interior edge
+ paint.setStrokeWidth(radius + 1);
// handle scale of radius due to CTM
SkScalar maxScale = canvas->getTotalMatrix().getMaxScale();
radius *= maxScale;
unsigned char gray = (unsigned char)(ambientAlpha*umbraAlpha*255.999f);
- SkASSERT(radius < 256);
- // convert the radius to fixed point 8.8 and
- // place it in the G,B components of the color
- unsigned char intPart = (unsigned char)radius;
- SkScalar fracPart = radius - intPart;
- paint.setColor(SkColorSetARGB(1, gray, intPart, (unsigned char)(fracPart*256.f)));
+ SkASSERT(radius < 64);
+ // Convert radius to 6.2 fixed point and place in the G component.
+ paint.setColor(SkColorSetARGB(1, gray, (unsigned char)(4.0f*radius), 0));
sk_sp<SkShader> gaussShader = SkGaussianEdgeShader::Make();
paint.setShader(gaussShader);
@@ -265,15 +267,6 @@ protected:
return;
}
- SkRect pathRect;
- SkRRect pathRRect;
- if ((!path.isOval(&pathRect) || pathRect.width() != pathRect.height()) &&
- (!path.isRRect(&pathRRect) || !pathRRect.allCornersCircular()) &&
- !path.isRect(&pathRect)) {
- this->drawSpotShadow(canvas, path, zValue, lightPos, lightWidth, spotAlpha);
- return;
- }
-
SkScalar zRatio = zValue / (lightPos.fZ - zValue);
if (zRatio < 0.0f) {
zRatio = 0.0f;
@@ -282,15 +275,26 @@ protected:
}
SkScalar radius = lightWidth*zRatio;
- // For all of these, we outset the rect by the radius to get our coverage shape.
+ SkRect pathRect;
+ SkRRect pathRRect;
+ if (radius >= 64 ||
+ !((path.isOval(&pathRect) && pathRect.width() == pathRect.height()) ||
+ (path.isRRect(&pathRRect) && pathRRect.allCornersCircular()) ||
+ path.isRect(&pathRect))) {
+ this->drawSpotShadow(canvas, path, zValue, lightPos, lightWidth, spotAlpha);
+ return;
+ }
+
+ // For all of these, we outset the rect by half the radius to get our stroke shape.
+ SkScalar halfRadius = SK_ScalarHalf*radius;
if (path.isOval(nullptr)) {
- pathRect.outset(radius, radius);
+ pathRect.outset(halfRadius, halfRadius);
pathRRect = SkRRect::MakeOval(pathRect);
} else if (path.isRect(nullptr)) {
- pathRect.outset(radius, radius);
- pathRRect = SkRRect::MakeRectXY(pathRect, radius, radius);
+ pathRect.outset(halfRadius, halfRadius);
+ pathRRect = SkRRect::MakeRectXY(pathRect, halfRadius, halfRadius);
} else {
- pathRRect.outset(radius, radius);
+ pathRRect.outset(halfRadius, halfRadius);
}
// compute the transformation params
@@ -302,18 +306,34 @@ protected:
SkPaint paint;
paint.setAntiAlias(true);
+ // We outset the stroke by the length of the translation so the shadow extends to
+ // the edge of the shape. We also add 1/2 to cover up AA on the interior edge.
+ SkScalar pad = offset.length() + 0.5f;
+ // compute area
+ SkScalar strokeWidth = radius + 2.0f*pad;
+ SkScalar strokedArea = 2.0f*strokeWidth*(pathRRect.width() + pathRRect.height());
+ SkScalar filledArea = (pathRRect.height() + radius)*(pathRRect.width() + radius);
+ // If the area of the stroked geometry is larger than the fill geometry, or
+ // if our pad is too big to convert to 6.2 fixed point, just fill it.
+ if (strokedArea > filledArea || pad >= 64) {
+ pad = 0;
+ paint.setStyle(SkPaint::kStrokeAndFill_Style);
+ paint.setStrokeWidth(radius);
+ } else {
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(strokeWidth);
+ }
sk_sp<SkShader> gaussShader = SkGaussianEdgeShader::Make();
paint.setShader(gaussShader);
// handle scale of radius due to CTM
SkScalar maxScale = canvas->getTotalMatrix().getMaxScale();
radius *= maxScale;
unsigned char gray = (unsigned char)(spotAlpha*255.999f);
- SkASSERT(radius < 256);
- // convert the radius to fixed point 8.8 and
- // place it in the G,B components of the color
- unsigned char intPart = (unsigned char)radius;
- SkScalar fracPart = radius - intPart;
- paint.setColor(SkColorSetARGB(1, gray, intPart, (unsigned char)(fracPart*256.f)));
+ SkASSERT(radius < 64);
+ SkASSERT(pad < 64);
+ // Convert radius and pad to 6.2 fixed point and place in the G & B components.
+ paint.setColor(SkColorSetARGB(1, gray, (unsigned char)(radius*4.0f),
+ (unsigned char)(pad*4.0f)));
// apply transformation to shadow
canvas->translate(offset.fX, offset.fY);