1cb93a386Sopenharmony_ci
2cb93a386Sopenharmony_ci/*
3cb93a386Sopenharmony_ci * Copyright 2017 Google Inc.
4cb93a386Sopenharmony_ci *
5cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
6cb93a386Sopenharmony_ci * found in the LICENSE file.
7cb93a386Sopenharmony_ci */
8cb93a386Sopenharmony_ci#include "samplecode/Sample.h"
9cb93a386Sopenharmony_ci#include "tools/Resources.h"
10cb93a386Sopenharmony_ci
11cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h"
12cb93a386Sopenharmony_ci#include "include/core/SkFont.h"
13cb93a386Sopenharmony_ci#include "include/core/SkImage.h"
14cb93a386Sopenharmony_ci#include "include/core/SkPath.h"
15cb93a386Sopenharmony_ci#include "include/core/SkPoint3.h"
16cb93a386Sopenharmony_ci#include "include/utils/SkShadowUtils.h"
17cb93a386Sopenharmony_ci
18cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////
19cb93a386Sopenharmony_ci// Sample to demonstrate tonal color shadows
20cb93a386Sopenharmony_ci
21cb93a386Sopenharmony_ciclass ShadowColorView : public Sample {
22cb93a386Sopenharmony_ci    SkPath    fRectPath;
23cb93a386Sopenharmony_ci    int       fZIndex;
24cb93a386Sopenharmony_ci
25cb93a386Sopenharmony_ci    bool      fShowAmbient;
26cb93a386Sopenharmony_ci    bool      fShowSpot;
27cb93a386Sopenharmony_ci    bool      fUseAlt;
28cb93a386Sopenharmony_ci    bool      fShowObject;
29cb93a386Sopenharmony_ci    bool      fTwoPassColor;
30cb93a386Sopenharmony_ci    bool      fDarkBackground;
31cb93a386Sopenharmony_ci
32cb93a386Sopenharmony_cipublic:
33cb93a386Sopenharmony_ci    ShadowColorView()
34cb93a386Sopenharmony_ci        : fZIndex(8)
35cb93a386Sopenharmony_ci        , fShowAmbient(true)
36cb93a386Sopenharmony_ci        , fShowSpot(true)
37cb93a386Sopenharmony_ci        , fUseAlt(false)
38cb93a386Sopenharmony_ci        , fShowObject(true)
39cb93a386Sopenharmony_ci        , fTwoPassColor(false)
40cb93a386Sopenharmony_ci        , fDarkBackground(false) {}
41cb93a386Sopenharmony_ci
42cb93a386Sopenharmony_ciprotected:
43cb93a386Sopenharmony_ci    void onOnceBeforeDraw() override {
44cb93a386Sopenharmony_ci        fRectPath.addRect(SkRect::MakeXYWH(-50, -50, 100, 100));
45cb93a386Sopenharmony_ci    }
46cb93a386Sopenharmony_ci
47cb93a386Sopenharmony_ci    SkString name() override { return SkString("ShadowColor"); }
48cb93a386Sopenharmony_ci
49cb93a386Sopenharmony_ci    bool onChar(SkUnichar uni) override {
50cb93a386Sopenharmony_ci            bool handled = false;
51cb93a386Sopenharmony_ci            switch (uni) {
52cb93a386Sopenharmony_ci                case 'W':
53cb93a386Sopenharmony_ci                    fShowAmbient = !fShowAmbient;
54cb93a386Sopenharmony_ci                    handled = true;
55cb93a386Sopenharmony_ci                    break;
56cb93a386Sopenharmony_ci                case 'S':
57cb93a386Sopenharmony_ci                    fShowSpot = !fShowSpot;
58cb93a386Sopenharmony_ci                    handled = true;
59cb93a386Sopenharmony_ci                    break;
60cb93a386Sopenharmony_ci                case 'T':
61cb93a386Sopenharmony_ci                    fUseAlt = !fUseAlt;
62cb93a386Sopenharmony_ci                    handled = true;
63cb93a386Sopenharmony_ci                    break;
64cb93a386Sopenharmony_ci                case 'O':
65cb93a386Sopenharmony_ci                    fShowObject = !fShowObject;
66cb93a386Sopenharmony_ci                    handled = true;
67cb93a386Sopenharmony_ci                    break;
68cb93a386Sopenharmony_ci                case 'X':
69cb93a386Sopenharmony_ci                    fTwoPassColor = !fTwoPassColor;
70cb93a386Sopenharmony_ci                    handled = true;
71cb93a386Sopenharmony_ci                    break;
72cb93a386Sopenharmony_ci                case 'Z':
73cb93a386Sopenharmony_ci                    fDarkBackground = !fDarkBackground;
74cb93a386Sopenharmony_ci                    handled = true;
75cb93a386Sopenharmony_ci                    break;
76cb93a386Sopenharmony_ci                case '>':
77cb93a386Sopenharmony_ci                    fZIndex = std::min(9, fZIndex+1);
78cb93a386Sopenharmony_ci                    handled = true;
79cb93a386Sopenharmony_ci                    break;
80cb93a386Sopenharmony_ci                case '<':
81cb93a386Sopenharmony_ci                    fZIndex = std::max(0, fZIndex-1);
82cb93a386Sopenharmony_ci                    handled = true;
83cb93a386Sopenharmony_ci                    break;
84cb93a386Sopenharmony_ci                default:
85cb93a386Sopenharmony_ci                    break;
86cb93a386Sopenharmony_ci            }
87cb93a386Sopenharmony_ci            if (handled) {
88cb93a386Sopenharmony_ci                return true;
89cb93a386Sopenharmony_ci            }
90cb93a386Sopenharmony_ci            return false;
91cb93a386Sopenharmony_ci    }
92cb93a386Sopenharmony_ci
93cb93a386Sopenharmony_ci
94cb93a386Sopenharmony_ci    void drawShadowedPath(SkCanvas* canvas, const SkPath& path,
95cb93a386Sopenharmony_ci                          const SkPoint3& zPlaneParams,
96cb93a386Sopenharmony_ci                          const SkPaint& paint, SkScalar ambientAlpha,
97cb93a386Sopenharmony_ci                          const SkPoint3& lightPos, SkScalar lightWidth, SkScalar spotAlpha) {
98cb93a386Sopenharmony_ci        if (!fShowAmbient) {
99cb93a386Sopenharmony_ci            ambientAlpha = 0;
100cb93a386Sopenharmony_ci        }
101cb93a386Sopenharmony_ci        if (!fShowSpot) {
102cb93a386Sopenharmony_ci            spotAlpha = 0;
103cb93a386Sopenharmony_ci        }
104cb93a386Sopenharmony_ci        uint32_t flags = 0;
105cb93a386Sopenharmony_ci        if (fUseAlt) {
106cb93a386Sopenharmony_ci            flags |= SkShadowFlags::kGeometricOnly_ShadowFlag;
107cb93a386Sopenharmony_ci        }
108cb93a386Sopenharmony_ci
109cb93a386Sopenharmony_ci        if (fTwoPassColor) {
110cb93a386Sopenharmony_ci            SkColor ambientColor = SkColorSetARGB(ambientAlpha*255, 0, 0, 0);
111cb93a386Sopenharmony_ci            SkShadowUtils::DrawShadow(canvas, path, zPlaneParams,
112cb93a386Sopenharmony_ci                                      lightPos, lightWidth,
113cb93a386Sopenharmony_ci                                      ambientColor, SK_ColorTRANSPARENT, flags);
114cb93a386Sopenharmony_ci
115cb93a386Sopenharmony_ci            if (paint.getColor() != SK_ColorBLACK) {
116cb93a386Sopenharmony_ci                SkColor color = paint.getColor();
117cb93a386Sopenharmony_ci
118cb93a386Sopenharmony_ci                uint8_t max = std::max(std::max(SkColorGetR(color), SkColorGetG(color)),
119cb93a386Sopenharmony_ci                                     SkColorGetB(color));
120cb93a386Sopenharmony_ci                uint8_t min = std::min(std::min(SkColorGetR(color), SkColorGetG(color)),
121cb93a386Sopenharmony_ci                                     SkColorGetB(color));
122cb93a386Sopenharmony_ci                SkScalar luminance = 0.5f*(max + min) / 255.f;
123cb93a386Sopenharmony_ci                SkScalar alpha = (.6 - .4*luminance)*luminance*luminance + 0.3f;
124cb93a386Sopenharmony_ci                spotAlpha -= (alpha - 0.3f)*.5f;
125cb93a386Sopenharmony_ci                SkColor spotColor = SkColorSetARGB(alpha*SkColorGetA(color), SkColorGetR(color),
126cb93a386Sopenharmony_ci                                                   SkColorGetG(color), SkColorGetB(color));
127cb93a386Sopenharmony_ci
128cb93a386Sopenharmony_ci                SkShadowUtils::DrawShadow(canvas, path, zPlaneParams,
129cb93a386Sopenharmony_ci                                          lightPos, lightWidth,
130cb93a386Sopenharmony_ci                                          SK_ColorTRANSPARENT, spotColor, flags);
131cb93a386Sopenharmony_ci            }
132cb93a386Sopenharmony_ci
133cb93a386Sopenharmony_ci            SkColor spotGreyscale = SkColorSetARGB(spotAlpha * 255, 0, 0, 0);
134cb93a386Sopenharmony_ci            SkShadowUtils::DrawShadow(canvas, path, zPlaneParams,
135cb93a386Sopenharmony_ci                                      lightPos, lightWidth,
136cb93a386Sopenharmony_ci                                      SK_ColorTRANSPARENT, spotGreyscale, flags);
137cb93a386Sopenharmony_ci        } else {
138cb93a386Sopenharmony_ci            SkColor color = paint.getColor();
139cb93a386Sopenharmony_ci            SkColor baseAmbient = SkColorSetARGB(ambientAlpha*SkColorGetA(color),
140cb93a386Sopenharmony_ci                                                 SkColorGetR(color), SkColorGetG(color),
141cb93a386Sopenharmony_ci                                                 SkColorGetB(color));
142cb93a386Sopenharmony_ci            SkColor baseSpot = SkColorSetARGB(spotAlpha*SkColorGetA(color),
143cb93a386Sopenharmony_ci                                              SkColorGetR(color), SkColorGetG(color),
144cb93a386Sopenharmony_ci                                              SkColorGetB(color));
145cb93a386Sopenharmony_ci            SkColor tonalAmbient, tonalSpot;
146cb93a386Sopenharmony_ci            SkShadowUtils::ComputeTonalColors(baseAmbient, baseSpot, &tonalAmbient, &tonalSpot);
147cb93a386Sopenharmony_ci            SkShadowUtils::DrawShadow(canvas, path, zPlaneParams,
148cb93a386Sopenharmony_ci                                      lightPos, lightWidth,
149cb93a386Sopenharmony_ci                                      tonalAmbient, tonalSpot, flags);
150cb93a386Sopenharmony_ci        }
151cb93a386Sopenharmony_ci        if (fShowObject) {
152cb93a386Sopenharmony_ci            canvas->drawPath(path, paint);
153cb93a386Sopenharmony_ci        } else {
154cb93a386Sopenharmony_ci            SkPaint strokePaint;
155cb93a386Sopenharmony_ci
156cb93a386Sopenharmony_ci            strokePaint.setColor(paint.getColor());
157cb93a386Sopenharmony_ci            strokePaint.setStyle(SkPaint::kStroke_Style);
158cb93a386Sopenharmony_ci
159cb93a386Sopenharmony_ci            canvas->drawPath(path, strokePaint);
160cb93a386Sopenharmony_ci        }
161cb93a386Sopenharmony_ci    }
162cb93a386Sopenharmony_ci
163cb93a386Sopenharmony_ci    void onDrawContent(SkCanvas* canvas) override {
164cb93a386Sopenharmony_ci        const SkScalar kLightWidth = 600;
165cb93a386Sopenharmony_ci        const SkScalar kAmbientAlpha = 0.03f;
166cb93a386Sopenharmony_ci        const SkScalar kSpotAlpha = 0.25f;
167cb93a386Sopenharmony_ci
168cb93a386Sopenharmony_ci        const SkScalar kZValues[10] = { 1, 2, 3, 4, 6, 8, 9, 12, 16, 24 };
169cb93a386Sopenharmony_ci
170cb93a386Sopenharmony_ci        const SkColor kColors[30] = {
171cb93a386Sopenharmony_ci            // purples
172cb93a386Sopenharmony_ci            0xFF3A0072, 0xFF5D0099, 0xFF7F12B2, 0xFFA02AD1, 0xFFC245E5,
173cb93a386Sopenharmony_ci            0xFFE95AF9, 0xFFFC79F0, 0xFFFDA6F0, 0xFFFFCCF8, 0xFFFFE1F9,
174cb93a386Sopenharmony_ci            // oranges
175cb93a386Sopenharmony_ci            0xFFEA3200, 0xFFFF4E00, 0xFFFF7300, 0xFFFF9100, 0xFFFFB000,
176cb93a386Sopenharmony_ci            0xFFFFCE00, 0xFFFFE000, 0xFFFFF64D, 0xFFFFF98F, 0xFFFFFBCC,
177cb93a386Sopenharmony_ci            // teals
178cb93a386Sopenharmony_ci            0xFF004D51, 0xFF066266, 0xFF057F7F, 0xFF009999, 0xFF00B2B2,
179cb93a386Sopenharmony_ci            0xFF15CCBE, 0xFF25E5CE, 0xFF2CFFE0, 0xFF80FFEA, 0xFFB3FFF0
180cb93a386Sopenharmony_ci        };
181cb93a386Sopenharmony_ci
182cb93a386Sopenharmony_ci        SkFont font;
183cb93a386Sopenharmony_ci        SkPaint paint;
184cb93a386Sopenharmony_ci        paint.setAntiAlias(true);
185cb93a386Sopenharmony_ci        if (fDarkBackground) {
186cb93a386Sopenharmony_ci            canvas->drawColor(0xFF111111);
187cb93a386Sopenharmony_ci            paint.setColor(SK_ColorWHITE);
188cb93a386Sopenharmony_ci        } else {
189cb93a386Sopenharmony_ci            canvas->drawColor(0xFFEAEAEA);
190cb93a386Sopenharmony_ci            paint.setColor(SK_ColorBLACK);
191cb93a386Sopenharmony_ci        }
192cb93a386Sopenharmony_ci        if (fTwoPassColor) {
193cb93a386Sopenharmony_ci            canvas->drawString("Two pass", 10, 15, font, paint);
194cb93a386Sopenharmony_ci        } else {
195cb93a386Sopenharmony_ci            canvas->drawString("One pass", 10, 15, font, paint);
196cb93a386Sopenharmony_ci        }
197cb93a386Sopenharmony_ci
198cb93a386Sopenharmony_ci        SkPoint3 lightPos = { 75, -400, 600 };
199cb93a386Sopenharmony_ci        SkPoint3 zPlaneParams = SkPoint3::Make(0, 0, kZValues[fZIndex]);
200cb93a386Sopenharmony_ci        SkScalar yPos = 75;
201cb93a386Sopenharmony_ci
202cb93a386Sopenharmony_ci        for (int row = 0; row < 3; ++row) {
203cb93a386Sopenharmony_ci            lightPos.fX = 75;
204cb93a386Sopenharmony_ci            SkScalar xPos = 75;
205cb93a386Sopenharmony_ci            for (int col = 0; col < 10; ++col) {
206cb93a386Sopenharmony_ci                paint.setColor(kColors[10*row + col]);
207cb93a386Sopenharmony_ci
208cb93a386Sopenharmony_ci                canvas->save();
209cb93a386Sopenharmony_ci                canvas->translate(xPos, yPos);
210cb93a386Sopenharmony_ci                this->drawShadowedPath(canvas, fRectPath, zPlaneParams, paint, kAmbientAlpha,
211cb93a386Sopenharmony_ci                                       lightPos, kLightWidth, kSpotAlpha);
212cb93a386Sopenharmony_ci                canvas->restore();
213cb93a386Sopenharmony_ci
214cb93a386Sopenharmony_ci                lightPos.fX += 120;
215cb93a386Sopenharmony_ci                xPos += 120;
216cb93a386Sopenharmony_ci            }
217cb93a386Sopenharmony_ci
218cb93a386Sopenharmony_ci            lightPos.fY += 200;
219cb93a386Sopenharmony_ci            yPos += 200;
220cb93a386Sopenharmony_ci        }
221cb93a386Sopenharmony_ci    }
222cb93a386Sopenharmony_ci
223cb93a386Sopenharmony_ciprivate:
224cb93a386Sopenharmony_ci    using INHERITED = Sample;
225cb93a386Sopenharmony_ci};
226cb93a386Sopenharmony_ci
227cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////
228cb93a386Sopenharmony_ci
229cb93a386Sopenharmony_ciDEF_SAMPLE( return new ShadowColorView(); )
230