| Jim Van Verth | e770578 | 2017-05-04 14:00:59 -0400 | [diff] [blame] | 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 "SampleCode.h" | 
 | 9 | #include "SkAnimTimer.h" | 
 | 10 | #include "SkBlurMask.h" | 
 | 11 | #include "SkBlurMaskFilter.h" | 
 | 12 | #include "SkColorFilter.h" | 
 | 13 | #include "SkCamera.h" | 
 | 14 | #include "SkCanvas.h" | 
| Jim Van Verth | e770578 | 2017-05-04 14:00:59 -0400 | [diff] [blame] | 15 | #include "SkPath.h" | 
 | 16 | #include "SkPathOps.h" | 
 | 17 | #include "SkPoint3.h" | 
 | 18 | #include "SkShadowUtils.h" | 
 | 19 | #include "SkUtils.h" | 
 | 20 | #include "SkView.h" | 
 | 21 | #include "sk_tool_utils.h" | 
 | 22 |  | 
 | 23 | //////////////////////////////////////////////////////////////////////////// | 
 | 24 |  | 
 | 25 | class ShadowUtilsView : public SampleView { | 
 | 26 |     SkTArray<SkPath> fPaths; | 
 | 27 |     SkScalar         fZDelta; | 
 | 28 |  | 
 | 29 |     bool      fShowAmbient; | 
 | 30 |     bool      fShowSpot; | 
 | 31 |     bool      fUseAlt; | 
 | 32 |     bool      fShowObject; | 
 | 33 |     bool      fIgnoreShadowAlpha; | 
 | 34 |  | 
 | 35 | public: | 
 | 36 |     ShadowUtilsView() | 
 | 37 |         : fZDelta(0) | 
 | 38 |         , fShowAmbient(true) | 
 | 39 |         , fShowSpot(true) | 
 | 40 |         , fUseAlt(false) | 
 | 41 |         , fShowObject(false) | 
 | 42 |         , fIgnoreShadowAlpha(false) {} | 
 | 43 |  | 
 | 44 | protected: | 
 | 45 |     void onOnceBeforeDraw() override { | 
 | 46 |         fPaths.push_back().addRoundRect(SkRect::MakeWH(50, 50), 10, 10); | 
 | 47 |         SkRRect oddRRect; | 
 | 48 |         oddRRect.setNinePatch(SkRect::MakeWH(50, 50), 9, 13, 6, 16); | 
 | 49 |         fPaths.push_back().addRRect(oddRRect); | 
 | 50 |         fPaths.push_back().addRect(SkRect::MakeWH(50, 50)); | 
 | 51 |         fPaths.push_back().addCircle(25, 25, 25); | 
 | 52 |         fPaths.push_back().cubicTo(100, 50, 20, 100, 0, 0); | 
 | 53 |         fPaths.push_back().addOval(SkRect::MakeWH(20, 60)); | 
 | 54 |     } | 
 | 55 |  | 
 | 56 |     // overrides from SkEventSink | 
 | 57 |     bool onQuery(SkEvent* evt) override { | 
 | 58 |         if (SampleCode::TitleQ(*evt)) { | 
 | 59 |             SampleCode::TitleR(evt, "ShadowUtils"); | 
 | 60 |             return true; | 
 | 61 |         } | 
 | 62 |  | 
 | 63 |         SkUnichar uni; | 
 | 64 |         if (SampleCode::CharQ(*evt, &uni)) { | 
 | 65 |             bool handled = false; | 
 | 66 |             switch (uni) { | 
 | 67 |                 case 'W': | 
 | 68 |                     fShowAmbient = !fShowAmbient; | 
 | 69 |                     handled = true; | 
 | 70 |                     break; | 
 | 71 |                 case 'S': | 
 | 72 |                     fShowSpot = !fShowSpot; | 
 | 73 |                     handled = true; | 
 | 74 |                     break; | 
 | 75 |                 case 'T': | 
 | 76 |                     fUseAlt = !fUseAlt; | 
 | 77 |                     handled = true; | 
 | 78 |                     break; | 
 | 79 |                 case 'O': | 
 | 80 |                     fShowObject = !fShowObject; | 
 | 81 |                     handled = true; | 
 | 82 |                     break; | 
 | 83 |                 case '>': | 
 | 84 |                     fZDelta += 0.5f; | 
 | 85 |                     handled = true; | 
 | 86 |                     break; | 
 | 87 |                 case '<': | 
 | 88 |                     fZDelta -= 0.5f; | 
 | 89 |                     handled = true; | 
 | 90 |                     break; | 
 | 91 |                 case '?': | 
 | 92 |                     fIgnoreShadowAlpha = !fIgnoreShadowAlpha; | 
 | 93 |                     handled = true; | 
 | 94 |                     break; | 
 | 95 |                 default: | 
 | 96 |                     break; | 
 | 97 |             } | 
 | 98 |             if (handled) { | 
| Jim Van Verth | e770578 | 2017-05-04 14:00:59 -0400 | [diff] [blame] | 99 |                 return true; | 
 | 100 |             } | 
 | 101 |         } | 
 | 102 |         return this->INHERITED::onQuery(evt); | 
 | 103 |     } | 
 | 104 |  | 
 | 105 |     void drawBG(SkCanvas* canvas) { | 
| Jim Van Verth | 8d1e0ac | 2017-05-05 15:53:23 -0400 | [diff] [blame] | 106 |         canvas->drawColor(0xFFFFFFFF); | 
| Jim Van Verth | e770578 | 2017-05-04 14:00:59 -0400 | [diff] [blame] | 107 |     } | 
 | 108 |  | 
 | 109 |     void drawShadowedPath(SkCanvas* canvas, const SkPath& path, | 
| Jim Van Verth | e308a12 | 2017-05-08 14:19:30 -0400 | [diff] [blame] | 110 |                           const SkPoint3& zPlaneParams, | 
| Jim Van Verth | e770578 | 2017-05-04 14:00:59 -0400 | [diff] [blame] | 111 |                           const SkPaint& paint, SkScalar ambientAlpha, | 
 | 112 |                           const SkPoint3& lightPos, SkScalar lightWidth, SkScalar spotAlpha, | 
 | 113 |                           uint32_t flags) { | 
 | 114 |         if (fIgnoreShadowAlpha) { | 
 | 115 |             ambientAlpha = 255; | 
 | 116 |             spotAlpha = 255; | 
 | 117 |         } | 
 | 118 |         if (!fShowAmbient) { | 
 | 119 |             ambientAlpha = 0; | 
 | 120 |         } | 
 | 121 |         if (!fShowSpot) { | 
 | 122 |             spotAlpha = 0; | 
 | 123 |         } | 
 | 124 |         if (fUseAlt) { | 
 | 125 |             flags |= SkShadowFlags::kGeometricOnly_ShadowFlag; | 
 | 126 |         } | 
| Jim Van Verth | a556684 | 2018-02-22 10:58:34 -0500 | [diff] [blame^] | 127 |  | 
 | 128 |         SkColor ambientColor = SkColorSetARGB(ambientAlpha * 255, 255, 0, 0); | 
 | 129 |         SkColor spotColor = SkColorSetARGB(spotAlpha * 255, 0, 0, 255); | 
| Jim Van Verth | 37c5a96 | 2017-05-10 14:13:24 -0400 | [diff] [blame] | 130 |         SkShadowUtils::DrawShadow(canvas, path, zPlaneParams, | 
 | 131 |                                   lightPos, lightWidth, | 
| Jim Van Verth | a556684 | 2018-02-22 10:58:34 -0500 | [diff] [blame^] | 132 |                                   ambientColor, spotColor, flags); | 
| Jim Van Verth | e770578 | 2017-05-04 14:00:59 -0400 | [diff] [blame] | 133 |  | 
 | 134 |         if (fShowObject) { | 
 | 135 |             canvas->drawPath(path, paint); | 
 | 136 |         } else { | 
 | 137 |             SkPaint strokePaint; | 
 | 138 |  | 
 | 139 |             strokePaint.setColor(paint.getColor()); | 
 | 140 |             strokePaint.setStyle(SkPaint::kStroke_Style); | 
 | 141 |  | 
 | 142 |             canvas->drawPath(path, strokePaint); | 
 | 143 |         } | 
 | 144 |     } | 
 | 145 |  | 
 | 146 |     void onDrawContent(SkCanvas* canvas) override { | 
 | 147 |         this->drawBG(canvas); | 
 | 148 |  | 
 | 149 |         static constexpr int kW = 800; | 
 | 150 |         static constexpr SkScalar kPad = 15.f; | 
| Jim Van Verth | e770578 | 2017-05-04 14:00:59 -0400 | [diff] [blame] | 151 |         static constexpr SkScalar kLightR = 100.f; | 
 | 152 |         static constexpr SkScalar kHeight = 50.f; | 
 | 153 |         static constexpr SkScalar kAmbientAlpha = 0.5f; | 
 | 154 |         static constexpr SkScalar kSpotAlpha = 0.5f; | 
| Jim Van Verth | 8793e38 | 2017-05-22 15:52:21 -0400 | [diff] [blame] | 155 |         static constexpr SkPoint3 lightPos = { 250, 400, 500 }; | 
| Jim Van Verth | 9392f569c | 2017-05-16 15:01:43 -0400 | [diff] [blame] | 156 |  | 
| Jim Van Verth | e770578 | 2017-05-04 14:00:59 -0400 | [diff] [blame] | 157 |         canvas->translate(3 * kPad, 3 * kPad); | 
 | 158 |         canvas->save(); | 
 | 159 |         SkScalar x = 0; | 
 | 160 |         SkScalar dy = 0; | 
 | 161 |         SkTDArray<SkMatrix> matrices; | 
 | 162 |         matrices.push()->reset(); | 
 | 163 |         SkMatrix* m = matrices.push(); | 
 | 164 |         m->setRotate(33.f, 25.f, 25.f); | 
 | 165 |         m->postScale(1.2f, 0.8f, 25.f, 25.f); | 
 | 166 |         SkPaint paint; | 
 | 167 |         paint.setColor(SK_ColorGREEN); | 
 | 168 |         paint.setAntiAlias(true); | 
| Jim Van Verth | e308a12 | 2017-05-08 14:19:30 -0400 | [diff] [blame] | 169 |         SkPoint3 zPlaneParams = SkPoint3::Make(0, 0, SkTMax(1.0f, kHeight + fZDelta)); | 
| Jim Van Verth | e770578 | 2017-05-04 14:00:59 -0400 | [diff] [blame] | 170 |         for (auto& m : matrices) { | 
 | 171 |             for (auto flags : { kNone_ShadowFlag, kTransparentOccluder_ShadowFlag }) { | 
 | 172 |                 for (const auto& path : fPaths) { | 
 | 173 |                     SkRect postMBounds = path.getBounds(); | 
 | 174 |                     m.mapRect(&postMBounds); | 
 | 175 |                     SkScalar w = postMBounds.width() + kHeight; | 
 | 176 |                     SkScalar dx = w + kPad; | 
 | 177 |                     if (x + dx > kW - 3 * kPad) { | 
 | 178 |                         canvas->restore(); | 
 | 179 |                         canvas->translate(0, dy); | 
 | 180 |                         canvas->save(); | 
 | 181 |                         x = 0; | 
 | 182 |                         dy = 0; | 
 | 183 |                     } | 
 | 184 |  | 
 | 185 |                     canvas->save(); | 
 | 186 |                     canvas->concat(m); | 
| Jim Van Verth | 9392f569c | 2017-05-16 15:01:43 -0400 | [diff] [blame] | 187 |                     drawShadowedPath(canvas, path, zPlaneParams, paint, kAmbientAlpha, lightPos, | 
| Jim Van Verth | e308a12 | 2017-05-08 14:19:30 -0400 | [diff] [blame] | 188 |                                      kLightR, kSpotAlpha, flags); | 
| Jim Van Verth | e770578 | 2017-05-04 14:00:59 -0400 | [diff] [blame] | 189 |                     canvas->restore(); | 
 | 190 |  | 
 | 191 |                     canvas->translate(dx, 0); | 
 | 192 |                     x += dx; | 
 | 193 |                     dy = SkTMax(dy, postMBounds.height() + kPad + kHeight); | 
 | 194 |                 } | 
 | 195 |             } | 
 | 196 |         } | 
 | 197 |         // Show where the light is in x,y as a circle (specified in device space). | 
 | 198 |         SkMatrix invCanvasM = canvas->getTotalMatrix(); | 
 | 199 |         if (invCanvasM.invert(&invCanvasM)) { | 
 | 200 |             canvas->save(); | 
 | 201 |             canvas->concat(invCanvasM); | 
 | 202 |             SkPaint paint; | 
 | 203 |             paint.setColor(SK_ColorBLACK); | 
 | 204 |             paint.setAntiAlias(true); | 
| Jim Van Verth | 9392f569c | 2017-05-16 15:01:43 -0400 | [diff] [blame] | 205 |             canvas->drawCircle(lightPos.fX, lightPos.fY, kLightR / 10.f, paint); | 
| Jim Van Verth | e770578 | 2017-05-04 14:00:59 -0400 | [diff] [blame] | 206 |             canvas->restore(); | 
 | 207 |         } | 
 | 208 |     } | 
 | 209 |  | 
 | 210 | private: | 
 | 211 |     typedef SampleView INHERITED; | 
 | 212 | }; | 
 | 213 |  | 
 | 214 | ////////////////////////////////////////////////////////////////////////////// | 
 | 215 |  | 
 | 216 | static SkView* MyFactory() { return new ShadowUtilsView; } | 
 | 217 | static SkViewRegister reg(MyFactory); |