SampleShadowUtils.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. /*
  2. * Copyright 2017 Google Inc.
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #include "include/core/SkCanvas.h"
  8. #include "include/core/SkColorFilter.h"
  9. #include "include/core/SkPath.h"
  10. #include "include/core/SkPoint3.h"
  11. #include "include/effects/SkBlurMaskFilter.h"
  12. #include "include/pathops/SkPathOps.h"
  13. #include "include/utils/SkCamera.h"
  14. #include "include/utils/SkShadowUtils.h"
  15. #include "samplecode/Sample.h"
  16. #include "src/core/SkBlurMask.h"
  17. #include "src/utils/SkUTF.h"
  18. #include "tools/ToolUtils.h"
  19. ////////////////////////////////////////////////////////////////////////////
  20. class ShadowUtilsView : public Sample {
  21. SkTArray<SkPath> fConvexPaths;
  22. SkTArray<SkPath> fConcavePaths;
  23. SkScalar fZDelta;
  24. bool fShowAmbient;
  25. bool fShowSpot;
  26. bool fUseAlt;
  27. bool fShowObject;
  28. bool fIgnoreShadowAlpha;
  29. public:
  30. ShadowUtilsView()
  31. : fZDelta(0)
  32. , fShowAmbient(true)
  33. , fShowSpot(true)
  34. , fUseAlt(false)
  35. , fShowObject(false)
  36. , fIgnoreShadowAlpha(false) {}
  37. protected:
  38. void onOnceBeforeDraw() override {
  39. fConvexPaths.push_back().addRoundRect(SkRect::MakeWH(50, 50), 10, 10);
  40. SkRRect oddRRect;
  41. oddRRect.setNinePatch(SkRect::MakeWH(50, 50), 9, 13, 6, 16);
  42. fConvexPaths.push_back().addRRect(oddRRect);
  43. fConvexPaths.push_back().addRect(SkRect::MakeWH(50, 50));
  44. fConvexPaths.push_back().addCircle(25, 25, 25);
  45. fConvexPaths.push_back().cubicTo(100, 50, 20, 100, 0, 0);
  46. fConvexPaths.push_back().addOval(SkRect::MakeWH(20, 60));
  47. // star
  48. fConcavePaths.push_back().moveTo(0.0f, -33.3333f);
  49. fConcavePaths.back().lineTo(9.62f, -16.6667f);
  50. fConcavePaths.back().lineTo(28.867f, -16.6667f);
  51. fConcavePaths.back().lineTo(19.24f, 0.0f);
  52. fConcavePaths.back().lineTo(28.867f, 16.6667f);
  53. fConcavePaths.back().lineTo(9.62f, 16.6667f);
  54. fConcavePaths.back().lineTo(0.0f, 33.3333f);
  55. fConcavePaths.back().lineTo(-9.62f, 16.6667f);
  56. fConcavePaths.back().lineTo(-28.867f, 16.6667f);
  57. fConcavePaths.back().lineTo(-19.24f, 0.0f);
  58. fConcavePaths.back().lineTo(-28.867f, -16.6667f);
  59. fConcavePaths.back().lineTo(-9.62f, -16.6667f);
  60. fConcavePaths.back().close();
  61. // dumbbell
  62. fConcavePaths.push_back().moveTo(50, 0);
  63. fConcavePaths.back().cubicTo(100, 25, 60, 50, 50, 0);
  64. fConcavePaths.back().cubicTo(0, -25, 40, -50, 50, 0);
  65. }
  66. SkString name() override { return SkString("ShadowUtils"); }
  67. bool onChar(SkUnichar uni) override {
  68. bool handled = false;
  69. switch (uni) {
  70. case 'W':
  71. fShowAmbient = !fShowAmbient;
  72. handled = true;
  73. break;
  74. case 'S':
  75. fShowSpot = !fShowSpot;
  76. handled = true;
  77. break;
  78. case 'T':
  79. fUseAlt = !fUseAlt;
  80. handled = true;
  81. break;
  82. case 'O':
  83. fShowObject = !fShowObject;
  84. handled = true;
  85. break;
  86. case '>':
  87. fZDelta += 0.5f;
  88. handled = true;
  89. break;
  90. case '<':
  91. fZDelta -= 0.5f;
  92. handled = true;
  93. break;
  94. case '?':
  95. fIgnoreShadowAlpha = !fIgnoreShadowAlpha;
  96. handled = true;
  97. break;
  98. default:
  99. break;
  100. }
  101. if (handled) {
  102. return true;
  103. }
  104. return false;
  105. }
  106. void drawBG(SkCanvas* canvas) {
  107. canvas->drawColor(0xFFFFFFFF);
  108. }
  109. void drawShadowedPath(SkCanvas* canvas, const SkPath& path,
  110. const SkPoint3& zPlaneParams,
  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. }
  127. SkColor ambientColor = SkColorSetARGB(ambientAlpha * 255, 255, 0, 0);
  128. SkColor spotColor = SkColorSetARGB(spotAlpha * 255, 0, 0, 255);
  129. SkShadowUtils::DrawShadow(canvas, path, zPlaneParams,
  130. lightPos, lightWidth,
  131. ambientColor, spotColor, flags);
  132. if (fShowObject) {
  133. canvas->drawPath(path, paint);
  134. } else {
  135. SkPaint strokePaint;
  136. strokePaint.setColor(paint.getColor());
  137. strokePaint.setStyle(SkPaint::kStroke_Style);
  138. canvas->drawPath(path, strokePaint);
  139. }
  140. }
  141. void onDrawContent(SkCanvas* canvas) override {
  142. this->drawBG(canvas);
  143. static constexpr int kW = 800;
  144. static constexpr SkScalar kPad = 15.f;
  145. static constexpr SkScalar kLightR = 100.f;
  146. static constexpr SkScalar kHeight = 50.f;
  147. static constexpr SkScalar kAmbientAlpha = 0.5f;
  148. static constexpr SkScalar kSpotAlpha = 0.5f;
  149. static constexpr SkPoint3 lightPos = { 250, 400, 500 };
  150. canvas->translate(3 * kPad, 3 * kPad);
  151. canvas->save();
  152. SkScalar x = 0;
  153. SkScalar dy = 0;
  154. SkTDArray<SkMatrix> matrices;
  155. matrices.push()->reset();
  156. SkMatrix* m = matrices.push();
  157. m->setRotate(33.f, 25.f, 25.f);
  158. m->postScale(1.2f, 0.8f, 25.f, 25.f);
  159. SkPaint paint;
  160. paint.setColor(SK_ColorGREEN);
  161. paint.setAntiAlias(true);
  162. SkPoint3 zPlaneParams = SkPoint3::Make(0, 0, SkTMax(1.0f, kHeight + fZDelta));
  163. // convex paths
  164. for (auto& m : matrices) {
  165. for (auto flags : { kNone_ShadowFlag, kTransparentOccluder_ShadowFlag }) {
  166. for (const auto& path : fConvexPaths) {
  167. SkRect postMBounds = path.getBounds();
  168. m.mapRect(&postMBounds);
  169. SkScalar w = postMBounds.width() + kHeight;
  170. SkScalar dx = w + kPad;
  171. if (x + dx > kW - 3 * kPad) {
  172. canvas->restore();
  173. canvas->translate(0, dy);
  174. canvas->save();
  175. x = 0;
  176. dy = 0;
  177. }
  178. canvas->save();
  179. canvas->concat(m);
  180. this->drawShadowedPath(canvas, path, zPlaneParams, paint, kAmbientAlpha,
  181. lightPos, kLightR, kSpotAlpha, flags);
  182. canvas->restore();
  183. canvas->translate(dx, 0);
  184. x += dx;
  185. dy = SkTMax(dy, postMBounds.height() + kPad + kHeight);
  186. }
  187. }
  188. }
  189. // concave paths
  190. canvas->restore();
  191. canvas->translate(kPad, dy);
  192. canvas->save();
  193. x = kPad;
  194. dy = 0;
  195. for (auto& m : matrices) {
  196. for (const auto& path : fConcavePaths) {
  197. SkRect postMBounds = path.getBounds();
  198. m.mapRect(&postMBounds);
  199. SkScalar w = postMBounds.width();
  200. SkScalar dx = w + kPad;
  201. canvas->save();
  202. canvas->concat(m);
  203. this->drawShadowedPath(canvas, path, zPlaneParams, paint, kAmbientAlpha, lightPos,
  204. kLightR, kSpotAlpha, kNone_ShadowFlag);
  205. canvas->restore();
  206. canvas->translate(dx, 0);
  207. x += dx;
  208. dy = SkTMax(dy, postMBounds.height() + kPad + kHeight);
  209. }
  210. }
  211. // Show where the light is in x,y as a circle (specified in device space).
  212. SkMatrix invCanvasM = canvas->getTotalMatrix();
  213. if (invCanvasM.invert(&invCanvasM)) {
  214. canvas->save();
  215. canvas->concat(invCanvasM);
  216. SkPaint paint;
  217. paint.setColor(SK_ColorBLACK);
  218. paint.setAntiAlias(true);
  219. canvas->drawCircle(lightPos.fX, lightPos.fY, kLightR / 10.f, paint);
  220. canvas->restore();
  221. }
  222. }
  223. private:
  224. typedef Sample INHERITED;
  225. };
  226. //////////////////////////////////////////////////////////////////////////////
  227. DEF_SAMPLE( return new ShadowUtilsView(); )