skia2/samplecode/SampleAndroidShadows.cpp

337 lines
12 KiB
C++
Raw Normal View History

/*
* 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 "SampleCode.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 "SkUtils.h"
#include "SkView.h"
#include "sk_tool_utils.h"
////////////////////////////////////////////////////////////////////////////
class ShadowsView : public SampleView {
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);
}
// overrides from SkEventSink
bool onQuery(SkEvent* evt) override {
if (SampleCode::TitleQ(*evt)) {
SampleCode::TitleR(evt, "AndroidShadows");
return true;
}
SkUnichar uni;
if (SampleCode::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.1f;
const SkScalar kSpotAlpha = 0.25f;
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);
// 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.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);
}
bool onAnimate(const SkAnimTimer& timer) override {
Revert "Revert "Create new inset algorithm for spot shadows"" This reverts commit e7c85c45c4c0a97adc6711bb12ecacc36af4ba11. Reason for revert: <INSERT REASONING HERE> Original change's description: > Revert "Create new inset algorithm for spot shadows" > > This reverts commit e5f5bf5175e426ebb6aa234f4387831c898f20ad. > > Reason for revert: Breaking a bunch of bots. e.g: > > https://luci-milo.appspot.com/swarming/task/3519cae0a03c7b10/steps/dm/0/stdout > > Original change's description: > > Create new inset algorithm for spot shadows > > > > BUG=skia: > > > > Change-Id: If7c67c2a5b9beea28f86d13362a5156b46394d0e > > Reviewed-on: https://skia-review.googlesource.com/9875 > > Commit-Queue: Ravi Mistry <rmistry@google.com> > > Reviewed-by: Brian Salomon <bsalomon@google.com> > > Reviewed-by: Robert Phillips <robertphillips@google.com> > > > > TBR=jvanverth@google.com,bsalomon@google.com,rmistry@google.com,robertphillips@google.com,msarett@google.com,reviews@skia.org > NOPRESUBMIT=true > NOTREECHECKS=true > NOTRY=true > BUG=skia: > > Change-Id: I3d119ff631dbb1a41f873b9c8753d542ec91254e > Reviewed-on: https://skia-review.googlesource.com/10112 > Reviewed-by: Brian Salomon <bsalomon@google.com> > Commit-Queue: Brian Salomon <bsalomon@google.com> > TBR=jvanverth@google.com,bsalomon@google.com,rmistry@google.com,msarett@google.com,robertphillips@google.com,reviews@skia.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=skia: Change-Id: Ib3998300606d3a2e2fb3a14b2088cfad48363501 Reviewed-on: https://skia-review.googlesource.com/10113 Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Brian Salomon <bsalomon@google.com>
2017-03-24 16:07:20 +00:00
fAnimTranslate = timer.pingPong(30, 0, 200, -200);
fAnimAngle = timer.pingPong(15, 0, 0, 20);
if (fDoAlphaAnimation) {
fAnimAlpha = timer.pingPong(5, 0, 1, 0);
}
return true;
}
private:
typedef SampleView INHERITED;
};
//////////////////////////////////////////////////////////////////////////////
static SkView* MyFactory() { return new ShadowsView; }
static SkViewRegister reg(MyFactory);