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