Add Material Design shadow reference sample
authorJim Van Verth <jvanverth@google.com>
Tue, 23 May 2017 17:50:58 +0000 (13:50 -0400)
committerSkia Commit-Bot <skia-commit-bot@chromium.org>
Tue, 23 May 2017 18:12:15 +0000 (18:12 +0000)
Change-Id: I889a3f508407178c457f675c321880d869caf9ea
Reviewed-on: https://skia-review.googlesource.com/17717
Commit-Queue: Jim Van Verth <jvanverth@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
gn/samples.gni
resources/shadowreference.png [new file with mode: 0755]
samplecode/SampleShadowReference.cpp [new file with mode: 0755]

index 2397aa2..2f79a35 100644 (file)
@@ -82,6 +82,7 @@ samples_sources = [
   "$_samplecode/SampleRepeatTile.cpp",
   "$_samplecode/SampleShaders.cpp",
   "$_samplecode/SampleShaderText.cpp",
+  "$_samplecode/SampleShadowReference.cpp",
   "$_samplecode/SampleShadowUtils.cpp",
   "$_samplecode/SampleShip.cpp",
   "$_samplecode/SampleSlides.cpp",
diff --git a/resources/shadowreference.png b/resources/shadowreference.png
new file mode 100755 (executable)
index 0000000..cca6fff
Binary files /dev/null and b/resources/shadowreference.png differ
diff --git a/samplecode/SampleShadowReference.cpp b/samplecode/SampleShadowReference.cpp
new file mode 100755 (executable)
index 0000000..99ff4b2
--- /dev/null
@@ -0,0 +1,205 @@
+
+/*
+ * 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 "SampleCode.h"
+#include "Resources.h"
+#include "SkCanvas.h"
+#include "SkImage.h"
+#include "SkPath.h"
+#include "SkPoint3.h"
+#include "SkShadowUtils.h"
+
+////////////////////////////////////////////////////////////////////////////
+// Sample to compare the Material Design shadow reference to our results
+
+class ShadowRefView : public SampleView {
+    SkPath         fRRectPath;
+    sk_sp<SkImage> 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("shadowreference.png");
+    }
+
+    // overrides from SkEventSink
+    bool onQuery(SkEvent* evt) override {
+        if (SampleCode::TitleQ(*evt)) {
+            SampleCode::TitleR(evt, "ShadowReference");
+            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;
+                default:
+                    break;
+            }
+            if (handled) {
+                this->inval(nullptr);
+                return true;
+            }
+        }
+        return this->INHERITED::onQuery(evt);
+    }
+
+    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;
+        }
+        SkShadowUtils::DrawShadow(canvas, path, zPlaneParams,
+                                  lightPos, lightWidth,
+                                  ambientAlpha, spotAlpha, SK_ColorBLACK, 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:
+    typedef SampleView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new ShadowRefView; }
+static SkViewRegister reg(MyFactory);