blob: 99ff4b2c8b21dd2dbdc2b9d5e4eddd34cb12302c [file] [log] [blame]
Jim Van Verth623fadf2017-05-23 13:50:58 -04001
2/*
3 * Copyright 2017 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8#include "SampleCode.h"
9#include "Resources.h"
10#include "SkCanvas.h"
11#include "SkImage.h"
12#include "SkPath.h"
13#include "SkPoint3.h"
14#include "SkShadowUtils.h"
15
16////////////////////////////////////////////////////////////////////////////
17// Sample to compare the Material Design shadow reference to our results
18
19class ShadowRefView : public SampleView {
20 SkPath fRRectPath;
21 sk_sp<SkImage> fReferenceImage;
22
23 bool fShowAmbient;
24 bool fShowSpot;
25 bool fUseAlt;
26 bool fShowObject;
27
28public:
29 ShadowRefView()
30 : fShowAmbient(true)
31 , fShowSpot(true)
32 , fUseAlt(false)
33 , fShowObject(true) {}
34
35protected:
36 void onOnceBeforeDraw() override {
37 fRRectPath.addRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(-130, -128.5, 130, 128.5), 4, 4));
38 fReferenceImage = GetResourceAsImage("shadowreference.png");
39 }
40
41 // overrides from SkEventSink
42 bool onQuery(SkEvent* evt) override {
43 if (SampleCode::TitleQ(*evt)) {
44 SampleCode::TitleR(evt, "ShadowReference");
45 return true;
46 }
47
48 SkUnichar uni;
49 if (SampleCode::CharQ(*evt, &uni)) {
50 bool handled = false;
51 switch (uni) {
52 case 'W':
53 fShowAmbient = !fShowAmbient;
54 handled = true;
55 break;
56 case 'S':
57 fShowSpot = !fShowSpot;
58 handled = true;
59 break;
60 case 'T':
61 fUseAlt = !fUseAlt;
62 handled = true;
63 break;
64 case 'O':
65 fShowObject = !fShowObject;
66 handled = true;
67 break;
68 default:
69 break;
70 }
71 if (handled) {
72 this->inval(nullptr);
73 return true;
74 }
75 }
76 return this->INHERITED::onQuery(evt);
77 }
78
79 void drawBG(SkCanvas* canvas) {
80 canvas->drawColor(0xFFFFFFFF);
81 canvas->drawImage(fReferenceImage, 10, 30);
82 }
83
84 void drawShadowedPath(SkCanvas* canvas, const SkPath& path,
85 const SkPoint3& zPlaneParams,
86 const SkPaint& paint, SkScalar ambientAlpha,
87 const SkPoint3& lightPos, SkScalar lightWidth, SkScalar spotAlpha) {
88 if (!fShowAmbient) {
89 ambientAlpha = 0;
90 }
91 if (!fShowSpot) {
92 spotAlpha = 0;
93 }
94 uint32_t flags = 0;
95 if (fUseAlt) {
96 flags |= SkShadowFlags::kGeometricOnly_ShadowFlag;
97 }
98 SkShadowUtils::DrawShadow(canvas, path, zPlaneParams,
99 lightPos, lightWidth,
100 ambientAlpha, spotAlpha, SK_ColorBLACK, flags);
101
102 if (fShowObject) {
103 canvas->drawPath(path, paint);
104 } else {
105 SkPaint strokePaint;
106
107 strokePaint.setColor(paint.getColor());
108 strokePaint.setStyle(SkPaint::kStroke_Style);
109
110 canvas->drawPath(path, strokePaint);
111 }
112 }
113
114 void onDrawContent(SkCanvas* canvas) override {
115 this->drawBG(canvas);
116 const SkScalar kDP = 4; // the reference image is 4x bigger than it is displayed on
117 // on the web page, so we need to reflect that here and
118 // multiply the heights and light params accordingly
119 const SkScalar kLightWidth = kDP*400;
120 const SkScalar kAmbientAlpha = 0.03f;
121 const SkScalar kSpotAlpha = 0.35f;
122
123 SkPaint paint;
124 paint.setAntiAlias(true);
125 paint.setColor(SK_ColorWHITE);
126
127 SkPoint3 lightPos = { 175, -800, kDP * 600 };
128 SkScalar xPos = 230;
129 SkScalar yPos = 254.25f;
130 SkRect clipRect = SkRect::MakeXYWH(45, 75, 122, 250);
131 SkPoint clipDelta = SkPoint::Make(320, 0);
132 SkPoint3 zPlaneParams = SkPoint3::Make(0, 0, kDP * 2);
133
134 canvas->save();
135 canvas->clipRect(clipRect);
136 canvas->translate(xPos, yPos);
137 this->drawShadowedPath(canvas, fRRectPath, zPlaneParams, paint, kAmbientAlpha,
138 lightPos, kLightWidth, kSpotAlpha);
139 canvas->restore();
140
141 lightPos.fX += 320;
142 xPos += 320;
143 clipRect.offset(clipDelta);
144 zPlaneParams.fZ = kDP * 3;
145 canvas->save();
146 canvas->clipRect(clipRect);
147 canvas->translate(xPos, yPos);
148 this->drawShadowedPath(canvas, fRRectPath, zPlaneParams, paint, kAmbientAlpha,
149 lightPos, kLightWidth, kSpotAlpha);
150 canvas->restore();
151
152 lightPos.fX += 320;
153 xPos += 320;
154 clipRect.offset(clipDelta);
155 zPlaneParams.fZ = kDP * 4;
156 canvas->save();
157 canvas->clipRect(clipRect);
158 canvas->translate(xPos, yPos);
159 this->drawShadowedPath(canvas, fRRectPath, zPlaneParams, paint, kAmbientAlpha,
160 lightPos, kLightWidth, kSpotAlpha);
161 canvas->restore();
162
163 lightPos.fX += 320;
164 xPos += 320;
165 clipRect.offset(clipDelta);
166 zPlaneParams.fZ = kDP * 6;
167 canvas->save();
168 canvas->clipRect(clipRect);
169 canvas->translate(xPos, yPos);
170 this->drawShadowedPath(canvas, fRRectPath, zPlaneParams, paint, kAmbientAlpha,
171 lightPos, kLightWidth, kSpotAlpha);
172 canvas->restore();
173
174 lightPos.fX += 320;
175 xPos += 320;
176 clipRect.offset(clipDelta);
177 zPlaneParams.fZ = kDP * 8;
178 canvas->save();
179 canvas->clipRect(clipRect);
180 canvas->translate(xPos, yPos);
181 this->drawShadowedPath(canvas, fRRectPath, zPlaneParams, paint, kAmbientAlpha,
182 lightPos, kLightWidth, kSpotAlpha);
183 canvas->restore();
184
185 lightPos.fX += 320;
186 xPos += 320;
187 clipRect.offset(clipDelta);
188 zPlaneParams.fZ = kDP * 16;
189 canvas->save();
190 canvas->clipRect(clipRect);
191 canvas->translate(xPos, yPos);
192 this->drawShadowedPath(canvas, fRRectPath, zPlaneParams, paint, kAmbientAlpha,
193 lightPos, kLightWidth, kSpotAlpha);
194 canvas->restore();
195
196 }
197
198private:
199 typedef SampleView INHERITED;
200};
201
202//////////////////////////////////////////////////////////////////////////////
203
204static SkView* MyFactory() { return new ShadowRefView; }
205static SkViewRegister reg(MyFactory);