Chromium Code Reviews| Index: samplecode/SampleAndroidShadows.cpp |
| diff --git a/samplecode/SampleAndroidShadows.cpp b/samplecode/SampleAndroidShadows.cpp |
| index c7a2f63db17ab9982ec7384607be5d453038e2f4..64dbc68e1b399f808efdc93b731401d80b4afb20 100755 |
| --- a/samplecode/SampleAndroidShadows.cpp |
| +++ b/samplecode/SampleAndroidShadows.cpp |
| @@ -143,44 +143,45 @@ protected: |
| 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; |
| + |
| SkRect pathRect; |
| SkRRect pathRRect; |
| - if ((!path.isOval(&pathRect) || pathRect.width() != pathRect.height()) && |
| + 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; |
| } |
| - 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. |
| + // 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); |
|
robertphillips
2016/08/29 13:09:32
// Convert radius to 6.2 fixed point and place in
jvanverth1
2016/08/29 13:31:42
Done.
|
| - 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); |
| + paint.setColor(SkColorSetARGB(1, gray, (unsigned char)(4.0f*radius), 0)); |
| sk_sp<SkShader> gaussShader = SkGaussianEdgeShader::Make(); |
| paint.setShader(gaussShader); |
| @@ -265,15 +266,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 +274,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 +305,33 @@ 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 one to cover up AA on the interior edge. |
| + SkScalar pad = offset.length() + 1.0f; |
| + // 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 |
|
robertphillips
2016/08/29 13:09:33
add "6.2" before "fixed point" ?
jvanverth1
2016/08/29 13:31:42
Done.
|
| + // if our pad is too big to convert to 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); |
| + 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); |