aboutsummaryrefslogtreecommitdiffhomepage
path: root/samplecode/SampleAndroidShadows.cpp
diff options
context:
space:
mode:
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;
};