aboutsummaryrefslogtreecommitdiffhomepage
path: root/samplecode/SampleAndroidShadows.cpp
diff options
context:
space:
mode:
authorGravatar Jim Van Verth <jvanverth@google.com>2017-05-04 09:58:17 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-05-04 14:28:28 +0000
commit060d9820364b0cf09c7eb3bda449f24c3dcba2e2 (patch)
treec839d2c3129f90c281d3b0f2c642cf160675b056 /samplecode/SampleAndroidShadows.cpp
parentdb711c982bfaa805d2de5a253c55a680c30189e0 (diff)
Combine the ambient and spot alphas into the base color
for geometric shadows. This matches the analytic shadow approach better, and is color space invariant. Also includes cleanup in SampleAndroidShadows. Bug: skia:6546 Change-Id: I7a7cd060420dae741f967334c8b19542a14f0bcf Reviewed-on: https://skia-review.googlesource.com/15228 Commit-Queue: Jim Van Verth <jvanverth@google.com> Reviewed-by: Robert Phillips <robertphillips@google.com>
Diffstat (limited to 'samplecode/SampleAndroidShadows.cpp')
-rw-r--r--samplecode/SampleAndroidShadows.cpp351
1 files changed, 14 insertions, 337 deletions
diff --git a/samplecode/SampleAndroidShadows.cpp b/samplecode/SampleAndroidShadows.cpp
index 02b494ff20..99e5ff4556 100644
--- a/samplecode/SampleAndroidShadows.cpp
+++ b/samplecode/SampleAndroidShadows.cpp
@@ -21,8 +21,6 @@
#include "SkView.h"
#include "sk_tool_utils.h"
-#define USE_SHADOW_UTILS
-
////////////////////////////////////////////////////////////////////////////
class ShadowsView : public SampleView {
@@ -129,327 +127,27 @@ protected:
canvas->drawColor(0xFFDDDDDD);
}
- static void GetOcclRect(const SkPath& path, SkRect* occlRect) {
- SkRect pathRect;
- SkRRect pathRRect;
- if (path.isOval(&pathRect)) {
- *occlRect = sk_tool_utils::compute_central_occluder(SkRRect::MakeOval(pathRect));
- } else if (path.isRRect(&pathRRect)) {
- *occlRect = sk_tool_utils::compute_central_occluder(pathRRect);
- } else if (path.isRect(occlRect)) {
- // the inverse transform for the spot shadow occluder doesn't always get us
- // back to exactly the same position, so deducting a little slop
- occlRect->inset(1, 1);
- } else {
- *occlRect = SkRect::MakeEmpty();
- }
- }
-
- void drawAmbientShadow(SkCanvas* canvas, const SkPath& path, SkScalar zValue,
- SkScalar ambientAlpha) {
-
- if (ambientAlpha <= 0) {
- 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;
-
- // occlude blur
- SkRect occlRect;
- GetOcclRect(path, &occlRect);
- sk_sp<SkMaskFilter> mf = SkBlurMaskFilter::Make(kNormal_SkBlurStyle,
- SkBlurMask::ConvertRadiusToSigma(radius),
- occlRect,
- SkBlurMaskFilter::kNone_BlurFlag);
-
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setMaskFilter(std::move(mf));
- paint.setColor(SkColorSetARGB(fIgnoreShadowAlpha
- ? 255
- : (unsigned char)(ambientAlpha*umbraAlpha*255.999f), 0, 0, 0));
- canvas->drawPath(path, paint);
-
- // draw occlusion rect
-#if DRAW_OCCL_RECT
- SkPaint stroke;
- stroke.setStyle(SkPaint::kStroke_Style);
- stroke.setColor(SK_ColorBLUE);
- canvas->drawRect(occlRect, stroke);
-#endif
- }
-
- void drawAmbientShadowAlt(SkCanvas* canvas, const SkPath& path, SkScalar zValue,
- SkScalar ambientAlpha) {
-
- if (ambientAlpha <= 0) {
- 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;
- // distance to outer of edge of geometry from original shape edge
- SkScalar offset = radius*umbraAlpha;
-
- SkRect pathRect;
- SkRRect pathRRect;
- SkScalar scaleFactors[2];
- if (!canvas->getTotalMatrix().getMinMaxScales(scaleFactors)) {
- return;
- }
- if (scaleFactors[0] != scaleFactors[1] || radius*scaleFactors[0] >= 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 inset the offset rect by half the radius to get our stroke shape.
- SkScalar strokeOutset = offset - SK_ScalarHalf*radius;
- // Make sure we'll have a radius of at least 0.5 after xform
- if (strokeOutset*scaleFactors[0] < 0.5f) {
- strokeOutset = 0.5f / scaleFactors[0];
- }
- if (path.isOval(nullptr)) {
- pathRect.outset(strokeOutset, strokeOutset);
- pathRRect = SkRRect::MakeOval(pathRect);
- } else if (path.isRect(nullptr)) {
- pathRect.outset(strokeOutset, strokeOutset);
- pathRRect = SkRRect::MakeRectXY(pathRect, strokeOutset, strokeOutset);
- } else {
- pathRRect.outset(strokeOutset, strokeOutset);
- }
-
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kStroke_Style);
- // we outset the stroke a little to cover up AA on the interior edge
- SkScalar pad = 0.5f;
- paint.setStrokeWidth(radius + 2*pad);
- // handle scale of radius and pad due to CTM
- radius *= scaleFactors[0];
- pad *= scaleFactors[0];
- SkASSERT(radius < 16384);
- SkASSERT(pad < 64);
- // Convert radius to 14.2 fixed point and place in the R & G components.
- // Convert pad to 6.2 fixed point and place in the B component.
- uint16_t iRadius = (uint16_t)(radius*4.0f);
- unsigned char alpha = (unsigned char)(ambientAlpha*255.999f);
- paint.setColor(SkColorSetARGB(fIgnoreShadowAlpha ? 255 : alpha,
- iRadius >> 8, iRadius & 0xff,
- (unsigned char)(4.0f*pad)));
-
- paint.setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorBLACK, SkBlendMode::kModulate));
- paint.setShader(SkGaussianEdgeShader::Make());
- canvas->drawRRect(pathRRect, paint);
- }
-
- void drawSpotShadow(SkCanvas* canvas, const SkPath& path, SkScalar zValue,
- SkPoint3 lightPos, SkScalar lightWidth, SkScalar spotAlpha) {
- if (spotAlpha <= 0) {
- return;
- }
-
- SkScalar zRatio = zValue / (lightPos.fZ - zValue);
- if (zRatio < 0.0f) {
- zRatio = 0.0f;
- } else if (zRatio > 0.95f) {
- zRatio = 0.95f;
- }
- SkScalar blurRadius = lightWidth*zRatio;
-
- // compute the transformation params
- SkPoint center = SkPoint::Make(path.getBounds().centerX(), path.getBounds().centerY());
- SkMatrix ctmInverse;
- if (!canvas->getTotalMatrix().invert(&ctmInverse)) {
- return;
- }
- SkPoint lightPos2D = SkPoint::Make(lightPos.fX, lightPos.fY);
- ctmInverse.mapPoints(&lightPos2D, 1);
- SkPoint offset = SkPoint::Make(zRatio*(center.fX - lightPos2D.fX),
- zRatio*(center.fY - lightPos2D.fY));
- SkScalar scale = lightPos.fZ / (lightPos.fZ - zValue);
-
- SkAutoCanvasRestore acr(canvas, true);
-
- sk_sp<SkMaskFilter> mf = SkBlurMaskFilter::Make(kNormal_SkBlurStyle,
- SkBlurMask::ConvertRadiusToSigma(blurRadius),
- SkBlurMaskFilter::kNone_BlurFlag);
-
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setMaskFilter(std::move(mf));
- paint.setColor(SkColorSetARGB(fIgnoreShadowAlpha
- ? 255
- : (unsigned char)(spotAlpha*255.999f), 0, 0, 0));
-
- // apply transformation to shadow
- canvas->scale(scale, scale);
- canvas->translate(offset.fX, offset.fY);
- canvas->drawPath(path, paint);
- }
-
- void drawSpotShadowAlt(SkCanvas* canvas, const SkPath& path, SkScalar zValue,
- SkPoint3 lightPos, SkScalar lightWidth, SkScalar spotAlpha) {
- if (spotAlpha <= 0) {
- return;
- }
-
- SkScalar zRatio = zValue / (lightPos.fZ - zValue);
- if (zRatio < 0.0f) {
- zRatio = 0.0f;
- } else if (zRatio > 0.95f) {
- zRatio = 0.95f;
- }
- SkScalar radius = 2.0f*lightWidth*zRatio;
-
- SkRect pathRect;
- SkRRect pathRRect;
- SkScalar scaleFactors[2];
- if (!canvas->getTotalMatrix().getMinMaxScales(scaleFactors)) {
- return;
- }
- if (scaleFactors[0] != scaleFactors[1] || radius*scaleFactors[0] >= 16384 ||
- !((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 need to ensure we have a rrect with radius >= 0.5f in device space
- const SkScalar minRadius = SK_ScalarHalf/scaleFactors[0];
- if (path.isOval(nullptr)) {
- pathRRect = SkRRect::MakeOval(pathRect);
- } else if (path.isRect(nullptr)) {
- pathRRect = SkRRect::MakeRectXY(pathRect, minRadius, minRadius);
- } else {
- if (pathRRect.getSimpleRadii().fX < minRadius) {
- pathRRect.setRectXY(pathRRect.rect(), minRadius, minRadius);
- }
- }
-
- // compute the scale and translation for the shadow
- SkScalar scale = lightPos.fZ / (lightPos.fZ - zValue);
- SkRRect shadowRRect;
- pathRRect.transform(SkMatrix::MakeScale(scale, scale), &shadowRRect);
- SkPoint center = SkPoint::Make(shadowRRect.rect().centerX(), shadowRRect.rect().centerY());
- SkMatrix ctmInverse;
- if (!canvas->getTotalMatrix().invert(&ctmInverse)) {
- return;
- }
- SkPoint lightPos2D = SkPoint::Make(lightPos.fX, lightPos.fY);
- ctmInverse.mapPoints(&lightPos2D, 1);
- SkPoint offset = SkPoint::Make(zRatio*(center.fX - lightPos2D.fX),
- zRatio*(center.fY - lightPos2D.fY));
- SkAutoCanvasRestore acr(canvas, true);
-
- SkPaint paint;
- paint.setAntiAlias(true);
- // 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
- // stroke width but we also have to account for the scaling.
- // We also add 1/2 to cover up AA on the interior edge.
- SkScalar scaleOffset = (scale - 1.0f) * SkTMax(SkTMax(SkTAbs(pathRect.fLeft),
- SkTAbs(pathRect.fRight)),
- SkTMax(SkTAbs(pathRect.fTop),
- SkTAbs(pathRect.fBottom)));
- SkScalar insetAmount = offset.length() - (0.5f * radius) + scaleOffset + 0.5f;
-
- // compute area
- SkScalar strokeWidth = radius + insetAmount;
- SkScalar strokedArea = 2.0f*strokeWidth*(shadowRRect.width() + shadowRRect.height());
- SkScalar filledArea = (shadowRRect.height() + radius)*(shadowRRect.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) {
- paint.setStyle(SkPaint::kStrokeAndFill_Style);
- paint.setStrokeWidth(radius);
- } 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 = shadowRRect.rect().makeInset(insetAmount/2.0f, insetAmount/2.0f);
- SkScalar insetRad = SkTMax(shadowRRect.getSimpleRadii().fX - insetAmount/2.0f,
- minRadius);
-
- shadowRRect = SkRRect::MakeRectXY(insetRect, insetRad, insetRad);
- paint.setStyle(SkPaint::kStroke_Style);
- paint.setStrokeWidth(strokeWidth);
- }
- paint.setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorBLACK, SkBlendMode::kModulate));
- paint.setShader(SkGaussianEdgeShader::Make());
- // handle scale of radius due to CTM
- radius *= scaleFactors[0];
- // don't need to scale pad as it was computed from the transformed offset
- SkASSERT(radius < 16384);
- SkScalar pad = 0;
- SkASSERT(pad < 64);
- // Convert radius to 14.2 fixed point and place in the R & G components.
- // Convert pad to 6.2 fixed point and place in the B component.
- uint16_t iRadius = (uint16_t)(radius*4.0f);
- unsigned char alpha = (unsigned char)(spotAlpha*255.999f);
- paint.setColor(SkColorSetARGB(fIgnoreShadowAlpha ? 255 : alpha,
- iRadius >> 8, iRadius & 0xff,
- (unsigned char)(4.0f*pad)));
-
- // apply transformation to shadow
- canvas->translate(offset.fX, offset.fY);
- canvas->drawRRect(shadowRRect, paint);
- }
-
void drawShadowedPath(SkCanvas* canvas, const SkPath& path,
std::function<SkScalar(SkScalar, SkScalar)> zFunc,
const SkPaint& paint, SkScalar ambientAlpha,
const SkPoint3& lightPos, SkScalar lightWidth, SkScalar spotAlpha) {
-#ifdef USE_SHADOW_UTILS
- SkScalar zValue = zFunc(0, 0);
- if (fUseAlt) {
- if (fShowAmbient) {
- this->drawAmbientShadowAlt(canvas, path, zValue, ambientAlpha);
- }
- if (fShowSpot) {
- this->drawSpotShadowAlt(canvas, path, zValue, lightPos, lightWidth, spotAlpha);
- }
- } else {
- if (!fShowAmbient) {
- ambientAlpha = 0;
- }
- if (!fShowSpot) {
- spotAlpha = 0;
- }
-
- //SkShadowUtils::DrawShadow(canvas, path,
- // zValue,
- // lightPos, lightWidth,
- // ambientAlpha, spotAlpha, SK_ColorBLACK);
- SkShadowUtils::DrawUncachedShadow(canvas, path, zFunc,
- lightPos, lightWidth,
- ambientAlpha, spotAlpha, SK_ColorBLACK);
+ if (!fShowAmbient) {
+ ambientAlpha = 0;
}
-#else
- if (fShowAmbient) {
- if (fUseAlt) {
- this->drawAmbientShadowAlt(canvas, path, zValue, ambientAlpha);
- } else {
- this->drawAmbientShadow(canvas, path, zValue, ambientAlpha);
- }
+ if (!fShowSpot) {
+ spotAlpha = 0;
}
- if (fShowSpot) {
- if (fUseAlt) {
- this->drawSpotShadowAlt(canvas, path, zValue, lightPos, lightWidth, spotAlpha);
- } else {
- this->drawSpotShadow(canvas, path, zValue, lightPos, lightWidth, spotAlpha);
- }
+ uint32_t flags = 0;
+ if (fUseAlt) {
+ flags |= SkShadowFlags::kGeometricOnly_ShadowFlag;
}
-#endif
+ //SkShadowUtils::DrawShadow(canvas, path,
+ // zValue,
+ // lightPos, lightWidth,
+ // ambientAlpha, spotAlpha, SK_ColorBLACK, flags);
+ SkShadowUtils::DrawUncachedShadow(canvas, path, zFunc,
+ lightPos, lightWidth,
+ ambientAlpha, spotAlpha, SK_ColorBLACK, flags);
if (fShowObject) {
canvas->drawPath(path, paint);
@@ -577,27 +275,6 @@ protected:
return true;
}
-protected:
- SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
- return new SkView::Click(this);
- }
-
- bool onClick(Click *click) override {
- SkScalar x = click->fCurr.fX;
- SkScalar y = click->fCurr.fY;
-
- SkScalar dx = x - click->fPrev.fX;
- SkScalar dy = y - click->fPrev.fY;
-
- if (dx != 0 || dy != 0) {
- fLightPos.fX += dx;
- fLightPos.fY += dy;
- this->inval(nullptr);
- }
-
- return true;
- }
-
private:
typedef SampleView INHERITED;
};