/* * Copyright 2017 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "include/core/SkCanvas.h" #include "include/core/SkImage.h" #include "include/core/SkPath.h" #include "include/core/SkPoint3.h" #include "include/core/SkRRect.h" #include "include/utils/SkShadowUtils.h" #include "samplecode/Sample.h" #include "tools/Resources.h" //////////////////////////////////////////////////////////////////////////// // Sample to compare the Material Design shadow reference to our results class ShadowRefView : public Sample { SkPath fRRectPath; sk_sp fReferenceImage; bool fShowAmbient; bool fShowSpot; bool fUseAlt; bool fShowObject; public: ShadowRefView() : fShowAmbient(true) , fShowSpot(true) , fUseAlt(false) , fShowObject(true) {} protected: void onOnceBeforeDraw() override { fRRectPath.addRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(-130, -128.5, 130, 128.5), 4, 4)); fReferenceImage = GetResourceAsImage("images/shadowreference.png"); } SkString name() override { return SkString("ShadowReference"); } bool onChar(SkUnichar uni) override { 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; default: break; } if (handled) { return true; } return false; } void drawBG(SkCanvas* canvas) { canvas->drawColor(0xFFFFFFFF); canvas->drawImage(fReferenceImage, 10, 30); } void drawShadowedPath(SkCanvas* canvas, const SkPath& path, const SkPoint3& zPlaneParams, const SkPaint& paint, SkScalar ambientAlpha, const SkPoint3& lightPos, SkScalar lightWidth, SkScalar spotAlpha) { 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 kDP = 4; // the reference image is 4x bigger than it is displayed on // on the web page, so we need to reflect that here and // multiply the heights and light params accordingly const SkScalar kLightWidth = kDP*400; const SkScalar kAmbientAlpha = 0.03f; const SkScalar kSpotAlpha = 0.35f; SkPaint paint; paint.setAntiAlias(true); paint.setColor(SK_ColorWHITE); SkPoint3 lightPos = { 175, -800, kDP * 600 }; SkScalar xPos = 230; SkScalar yPos = 254.25f; SkRect clipRect = SkRect::MakeXYWH(45, 75, 122, 250); SkPoint clipDelta = SkPoint::Make(320, 0); SkPoint3 zPlaneParams = SkPoint3::Make(0, 0, kDP * 2); canvas->save(); canvas->clipRect(clipRect); canvas->translate(xPos, yPos); this->drawShadowedPath(canvas, fRRectPath, zPlaneParams, paint, kAmbientAlpha, lightPos, kLightWidth, kSpotAlpha); canvas->restore(); lightPos.fX += 320; xPos += 320; clipRect.offset(clipDelta); zPlaneParams.fZ = kDP * 3; canvas->save(); canvas->clipRect(clipRect); canvas->translate(xPos, yPos); this->drawShadowedPath(canvas, fRRectPath, zPlaneParams, paint, kAmbientAlpha, lightPos, kLightWidth, kSpotAlpha); canvas->restore(); lightPos.fX += 320; xPos += 320; clipRect.offset(clipDelta); zPlaneParams.fZ = kDP * 4; canvas->save(); canvas->clipRect(clipRect); canvas->translate(xPos, yPos); this->drawShadowedPath(canvas, fRRectPath, zPlaneParams, paint, kAmbientAlpha, lightPos, kLightWidth, kSpotAlpha); canvas->restore(); lightPos.fX += 320; xPos += 320; clipRect.offset(clipDelta); zPlaneParams.fZ = kDP * 6; canvas->save(); canvas->clipRect(clipRect); canvas->translate(xPos, yPos); this->drawShadowedPath(canvas, fRRectPath, zPlaneParams, paint, kAmbientAlpha, lightPos, kLightWidth, kSpotAlpha); canvas->restore(); lightPos.fX += 320; xPos += 320; clipRect.offset(clipDelta); zPlaneParams.fZ = kDP * 8; canvas->save(); canvas->clipRect(clipRect); canvas->translate(xPos, yPos); this->drawShadowedPath(canvas, fRRectPath, zPlaneParams, paint, kAmbientAlpha, lightPos, kLightWidth, kSpotAlpha); canvas->restore(); lightPos.fX += 320; xPos += 320; clipRect.offset(clipDelta); zPlaneParams.fZ = kDP * 16; canvas->save(); canvas->clipRect(clipRect); canvas->translate(xPos, yPos); this->drawShadowedPath(canvas, fRRectPath, zPlaneParams, paint, kAmbientAlpha, lightPos, kLightWidth, kSpotAlpha); canvas->restore(); } private: using INHERITED = Sample; }; ////////////////////////////////////////////////////////////////////////////// DEF_SAMPLE( return new ShadowRefView(); )