You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
359 lines
13 KiB
359 lines
13 KiB
|
|
/* |
|
* Copyright 2016 Google Inc. |
|
* |
|
* Use of this source code is governed by a BSD-style license that can be |
|
* found in the LICENSE file. |
|
*/ |
|
#include "Sample.h" |
|
#include "SkAnimTimer.h" |
|
#include "SkBlurMask.h" |
|
#include "SkBlurMaskFilter.h" |
|
#include "SkColorFilter.h" |
|
#include "SkCamera.h" |
|
#include "SkCanvas.h" |
|
#include "SkPath.h" |
|
#include "SkPathOps.h" |
|
#include "SkPoint3.h" |
|
#include "SkShadowUtils.h" |
|
#include "SkUTF.h" |
|
#include "sk_tool_utils.h" |
|
|
|
//////////////////////////////////////////////////////////////////////////// |
|
|
|
class ShadowsView : public Sample { |
|
SkPath fRectPath; |
|
SkPath fRRPath; |
|
SkPath fCirclePath; |
|
SkPath fFunkyRRPath; |
|
SkPath fCubicPath; |
|
SkPath fStarPath; |
|
SkPath fSquareRRectPath; |
|
SkPath fWideRectPath; |
|
SkPath fWideOvalPath; |
|
SkPath fNotchPath; |
|
SkPath fTabPath; |
|
|
|
SkPoint3 fLightPos; |
|
SkScalar fZDelta; |
|
SkScalar fAnimTranslate; |
|
SkScalar fAnimAngle; |
|
SkScalar fAnimAlpha; |
|
|
|
bool fShowAmbient; |
|
bool fShowSpot; |
|
bool fUseAlt; |
|
bool fShowObject; |
|
bool fIgnoreShadowAlpha; |
|
bool fDoAlphaAnimation; |
|
|
|
public: |
|
ShadowsView() |
|
: fZDelta(0) |
|
, fAnimTranslate(0) |
|
, fAnimAngle(0) |
|
, fAnimAlpha(1) |
|
, fShowAmbient(true) |
|
, fShowSpot(true) |
|
, fUseAlt(false) |
|
, fShowObject(true) |
|
, fIgnoreShadowAlpha(false) |
|
, fDoAlphaAnimation(false) {} |
|
|
|
protected: |
|
void onOnceBeforeDraw() override { |
|
fCirclePath.addCircle(0, 0, 50); |
|
fRectPath.addRect(SkRect::MakeXYWH(-100, -50, 200, 100)); |
|
fRRPath.addRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(-100, -50, 200, 100), 4, 4)); |
|
fFunkyRRPath.addRoundRect(SkRect::MakeXYWH(-50, -50, SK_Scalar1 * 100, SK_Scalar1 * 100), |
|
40 * SK_Scalar1, 20 * SK_Scalar1, |
|
SkPath::kCW_Direction); |
|
fCubicPath.cubicTo(100 * SK_Scalar1, 50 * SK_Scalar1, |
|
20 * SK_Scalar1, 100 * SK_Scalar1, |
|
0 * SK_Scalar1, 0 * SK_Scalar1); |
|
fStarPath.moveTo(0.0f, -50.0f); |
|
fStarPath.lineTo(14.43f, -25.0f); |
|
fStarPath.lineTo(43.30f, -25.0f); |
|
fStarPath.lineTo(28.86f, 0.0f); |
|
fStarPath.lineTo(43.30f, 25.0f); |
|
fStarPath.lineTo(14.43f, 25.0f); |
|
fStarPath.lineTo(0.0f, 50.0f); |
|
fStarPath.lineTo(-14.43f, 25.0f); |
|
fStarPath.lineTo(-43.30f, 25.0f); |
|
fStarPath.lineTo(-28.86f, 0.0f); |
|
fStarPath.lineTo(-43.30f, -25.0f); |
|
fStarPath.lineTo(-14.43f, -25.0f); |
|
fSquareRRectPath.addRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(-50, -50, 100, 100), |
|
10, 10)); |
|
fWideRectPath.addRect(SkRect::MakeXYWH(0, 0, 630, 70)); |
|
fWideOvalPath.addOval(SkRect::MakeXYWH(0, 0, 630, 70)); |
|
|
|
fNotchPath.moveTo(0, 80); |
|
fNotchPath.arcTo(SkRect::MakeLTRB(-20, 80, 20, 120), -90, -90, false); |
|
fNotchPath.lineTo(-75, 100); |
|
fNotchPath.lineTo(-75, -100); |
|
fNotchPath.lineTo(75, -100); |
|
fNotchPath.lineTo(75, 100); |
|
fNotchPath.arcTo(SkRect::MakeLTRB(-20, 80, 20, 120), 0, -90, false); |
|
|
|
fTabPath.moveTo(-75, -100); |
|
fTabPath.lineTo(75, -100); |
|
fTabPath.lineTo(75, 100); |
|
fTabPath.arcTo(SkRect::MakeLTRB(-20, 80, 20, 120), 0, 90, false); |
|
fTabPath.arcTo(SkRect::MakeLTRB(-20, 80, 20, 120), 90, 90, false); |
|
fTabPath.lineTo(-75, 100); |
|
|
|
fLightPos = SkPoint3::Make(350, 0, 600); |
|
} |
|
|
|
bool onQuery(Sample::Event* evt) override { |
|
if (Sample::TitleQ(*evt)) { |
|
Sample::TitleR(evt, "AndroidShadows"); |
|
return true; |
|
} |
|
|
|
SkUnichar uni; |
|
if (Sample::CharQ(*evt, &uni)) { |
|
bool handled = false; |
|
switch (uni) { |
|
case 'W': |
|
fShowAmbient = !fShowAmbient; |
|
handled = true; |
|
break; |
|
case 'S': |
|
fShowSpot = !fShowSpot; |
|
handled = true; |
|
break; |
|
case 'T': |
|
fUseAlt = !fUseAlt; |
|
handled = true; |
|
break; |
|
case 'O': |
|
fShowObject = !fShowObject; |
|
handled = true; |
|
break; |
|
case 'N': |
|
fDoAlphaAnimation = !fDoAlphaAnimation; |
|
if (!fDoAlphaAnimation) { |
|
fAnimAlpha = 1; |
|
} |
|
handled = true; |
|
break; |
|
case '>': |
|
fZDelta += 0.5f; |
|
handled = true; |
|
break; |
|
case '<': |
|
fZDelta -= 0.5f; |
|
handled = true; |
|
break; |
|
case '?': |
|
fIgnoreShadowAlpha = !fIgnoreShadowAlpha; |
|
handled = true; |
|
break; |
|
default: |
|
break; |
|
} |
|
if (handled) { |
|
return true; |
|
} |
|
} |
|
return this->INHERITED::onQuery(evt); |
|
} |
|
|
|
void drawBG(SkCanvas* canvas) { |
|
canvas->drawColor(0xFFDDDDDD); |
|
} |
|
|
|
void drawShadowedPath(SkCanvas* canvas, const SkPath& path, |
|
const SkPoint3& zPlaneParams, |
|
const SkPaint& paint, SkScalar ambientAlpha, |
|
const SkPoint3& lightPos, SkScalar lightWidth, SkScalar spotAlpha) { |
|
if (fIgnoreShadowAlpha) { |
|
ambientAlpha = 1; |
|
spotAlpha = 1; |
|
} |
|
if (!fShowAmbient) { |
|
ambientAlpha = 0; |
|
} |
|
if (!fShowSpot) { |
|
spotAlpha = 0; |
|
} |
|
uint32_t flags = 0; |
|
if (fUseAlt) { |
|
flags |= SkShadowFlags::kGeometricOnly_ShadowFlag; |
|
} |
|
|
|
SkColor ambientColor = SkColorSetARGB(ambientAlpha * 255, 0, 0, 0); |
|
SkColor spotColor = SkColorSetARGB(spotAlpha * 255, 0, 0, 0); |
|
SkShadowUtils::DrawShadow(canvas, path, zPlaneParams, lightPos, lightWidth, |
|
ambientColor, spotColor, flags); |
|
|
|
if (fShowObject) { |
|
canvas->drawPath(path, paint); |
|
} else { |
|
SkPaint strokePaint; |
|
|
|
strokePaint.setColor(paint.getColor()); |
|
strokePaint.setStyle(SkPaint::kStroke_Style); |
|
|
|
canvas->drawPath(path, strokePaint); |
|
} |
|
} |
|
|
|
void onDrawContent(SkCanvas* canvas) override { |
|
this->drawBG(canvas); |
|
const SkScalar kLightWidth = 800; |
|
const SkScalar kAmbientAlpha = 0.039f; |
|
const SkScalar kSpotAlpha = 0.19f; |
|
|
|
SkPaint paint; |
|
paint.setAntiAlias(true); |
|
|
|
SkPoint3 lightPos = fLightPos; |
|
SkPoint3 zPlaneParams = SkPoint3::Make(0, 0, 0); |
|
|
|
paint.setColor(SK_ColorWHITE); |
|
canvas->translate(200, 90); |
|
zPlaneParams.fZ = SkTMax(1.0f, 2 + fZDelta); |
|
this->drawShadowedPath(canvas, fRRPath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha, |
|
lightPos, kLightWidth, fAnimAlpha*kSpotAlpha); |
|
|
|
paint.setColor(SK_ColorRED); |
|
canvas->translate(250, 0); |
|
zPlaneParams.fZ = SkTMax(1.0f, 8 + fZDelta); |
|
this->drawShadowedPath(canvas, fRectPath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha, |
|
lightPos, kLightWidth, fAnimAlpha*kSpotAlpha); |
|
|
|
paint.setColor(SK_ColorBLUE); |
|
canvas->translate(-250, 110); |
|
zPlaneParams.fZ = SkTMax(1.0f, 12 + fZDelta); |
|
this->drawShadowedPath(canvas, fCirclePath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha, |
|
lightPos, kLightWidth, fAnimAlpha*0.5f); |
|
|
|
paint.setColor(SK_ColorGREEN); |
|
canvas->translate(250, 0); |
|
zPlaneParams.fZ = SkTMax(1.0f, 64 + fZDelta); |
|
this->drawShadowedPath(canvas, fRRPath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha, |
|
lightPos, kLightWidth, fAnimAlpha*kSpotAlpha); |
|
|
|
paint.setColor(SK_ColorYELLOW); |
|
canvas->translate(-250, 110); |
|
zPlaneParams.fZ = SkTMax(1.0f, 8 + fZDelta); |
|
this->drawShadowedPath(canvas, fFunkyRRPath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha, |
|
lightPos, kLightWidth, fAnimAlpha*kSpotAlpha); |
|
|
|
paint.setColor(SK_ColorCYAN); |
|
canvas->translate(250, 0); |
|
zPlaneParams.fZ = SkTMax(1.0f, 16 + fZDelta); |
|
this->drawShadowedPath(canvas, fCubicPath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha, |
|
lightPos, kLightWidth, fAnimAlpha*kSpotAlpha); |
|
|
|
paint.setColor(SK_ColorWHITE); |
|
canvas->translate(250, -180); |
|
zPlaneParams.fZ = SkTMax(1.0f, 8 + fZDelta); |
|
this->drawShadowedPath(canvas, fStarPath, zPlaneParams, paint, |
|
kAmbientAlpha, lightPos, kLightWidth, kSpotAlpha); |
|
|
|
paint.setColor(SK_ColorWHITE); |
|
canvas->translate(150, 0); |
|
zPlaneParams.fZ = SkTMax(1.0f, 2 + fZDelta); |
|
this->drawShadowedPath(canvas, fNotchPath, zPlaneParams, paint, |
|
kAmbientAlpha, lightPos, kLightWidth, kSpotAlpha); |
|
|
|
paint.setColor(SK_ColorWHITE); |
|
canvas->translate(200, 0); |
|
zPlaneParams.fZ = SkTMax(1.0f, 16 + fZDelta); |
|
this->drawShadowedPath(canvas, fTabPath, zPlaneParams, paint, |
|
kAmbientAlpha, lightPos, kLightWidth, kSpotAlpha); |
|
|
|
// circular reveal |
|
SkPath tmpPath; |
|
SkPath tmpClipPath; |
|
tmpClipPath.addCircle(fAnimTranslate, 0, 60); |
|
Op(fSquareRRectPath, tmpClipPath, kIntersect_SkPathOp, &tmpPath); |
|
|
|
paint.setColor(SK_ColorMAGENTA); |
|
canvas->translate(-725, 240); |
|
zPlaneParams.fZ = SkTMax(1.0f, 32 + fZDelta); |
|
this->drawShadowedPath(canvas, tmpPath, zPlaneParams, paint, .1f, |
|
lightPos, kLightWidth, .5f); |
|
|
|
// path ops bug |
|
SkPath tmpClipPathBug; |
|
tmpClipPathBug.addCircle(88.0344925f, 0, 60); |
|
Op(fSquareRRectPath, tmpClipPathBug, kIntersect_SkPathOp, &tmpPath); |
|
|
|
canvas->translate(250, 0); |
|
zPlaneParams.fZ = SkTMax(1.0f, 32 + fZDelta); |
|
this->drawShadowedPath(canvas, tmpPath, zPlaneParams, paint, .1f, |
|
lightPos, kLightWidth, .5f); |
|
|
|
// perspective paths |
|
SkPoint pivot = SkPoint::Make(fWideRectPath.getBounds().width()/2, |
|
fWideRectPath.getBounds().height()/2); |
|
SkPoint translate = SkPoint::Make(100, 450); |
|
paint.setColor(SK_ColorWHITE); |
|
Sk3DView view; |
|
view.save(); |
|
view.rotateX(fAnimAngle); |
|
SkMatrix persp; |
|
view.getMatrix(&persp); |
|
persp.preTranslate(-pivot.fX, -pivot.fY); |
|
persp.postTranslate(pivot.fX + translate.fX, pivot.fY + translate.fY); |
|
canvas->setMatrix(persp); |
|
SkScalar radians = SkDegreesToRadians(fAnimAngle); |
|
zPlaneParams = SkPoint3::Make(0, |
|
SkScalarSin(radians), |
|
SkTMax(1.0f, 16 + fZDelta) - SkScalarSin(radians)*pivot.fY); |
|
this->drawShadowedPath(canvas, fWideRectPath, zPlaneParams, paint, .1f, |
|
lightPos, kLightWidth, .5f); |
|
|
|
pivot = SkPoint::Make(fWideOvalPath.getBounds().width() / 2, |
|
fWideOvalPath.getBounds().height() / 2); |
|
translate = SkPoint::Make(100, 600); |
|
view.restore(); |
|
view.save(); |
|
view.rotateY(fAnimAngle); |
|
view.getMatrix(&persp); |
|
persp.preTranslate(-pivot.fX, -pivot.fY); |
|
persp.postTranslate(pivot.fX + translate.fX, pivot.fY + translate.fY); |
|
canvas->setMatrix(persp); |
|
zPlaneParams = SkPoint3::Make(-SkScalarSin(radians), |
|
0, |
|
SkTMax(1.0f, 32 + fZDelta) + SkScalarSin(radians)*pivot.fX); |
|
this->drawShadowedPath(canvas, fWideOvalPath, zPlaneParams, paint, .1f, |
|
lightPos, kLightWidth, .5f); |
|
|
|
pivot = SkPoint::Make(fStarPath.getBounds().width() / 2, |
|
fStarPath.getBounds().height() / 2); |
|
translate = SkPoint::Make(700, 250); |
|
view.restore(); |
|
view.rotateY(fAnimAngle); |
|
view.getMatrix(&persp); |
|
persp.preTranslate(-pivot.fX, -pivot.fY); |
|
persp.postTranslate(pivot.fX + translate.fX, pivot.fY + translate.fY); |
|
canvas->setMatrix(persp); |
|
zPlaneParams = SkPoint3::Make(-SkScalarSin(radians), |
|
0, |
|
SkTMax(1.0f, 8 + fZDelta) + SkScalarSin(radians)*pivot.fX); |
|
this->drawShadowedPath(canvas, fStarPath, zPlaneParams, paint, .1f, |
|
lightPos, kLightWidth, .5f); |
|
} |
|
|
|
bool onAnimate(const SkAnimTimer& timer) override { |
|
fAnimTranslate = timer.pingPong(30, 0, 125, -125); |
|
fAnimAngle = timer.pingPong(15, 0, 0, 20); |
|
if (fDoAlphaAnimation) { |
|
fAnimAlpha = timer.pingPong(5, 0, 1, 0); |
|
} |
|
return true; |
|
} |
|
|
|
private: |
|
typedef Sample INHERITED; |
|
}; |
|
|
|
////////////////////////////////////////////////////////////////////////////// |
|
|
|
DEF_SAMPLE( return new ShadowsView(); )
|
|
|