Index: samplecode/SampleAndroidShadows.cpp |
diff --git a/samplecode/SampleAndroidShadows.cpp b/samplecode/SampleAndroidShadows.cpp |
index c7a2f63db17ab9982ec7384607be5d453038e2f4..f411e5c9b3999301ce7ff9298f30e174c7648828 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); |