SampleAndroidShadows.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. /*
  2. * Copyright 2016 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. #include "tools/timer/TimeUtils.h"
  20. ////////////////////////////////////////////////////////////////////////////
  21. class ShadowsView : public Sample {
  22. SkPath fRectPath;
  23. SkPath fRRPath;
  24. SkPath fCirclePath;
  25. SkPath fFunkyRRPath;
  26. SkPath fCubicPath;
  27. SkPath fStarPath;
  28. SkPath fSquareRRectPath;
  29. SkPath fWideRectPath;
  30. SkPath fWideOvalPath;
  31. SkPath fNotchPath;
  32. SkPath fTabPath;
  33. SkPoint3 fLightPos;
  34. SkScalar fZDelta = 0;
  35. SkScalar fAnimTranslate = 0;
  36. SkScalar fAnimAngle = 0;
  37. SkScalar fAnimAlpha = 1;
  38. bool fShowAmbient = true;
  39. bool fShowSpot = true;
  40. bool fUseAlt = false;
  41. bool fShowObject = true;
  42. bool fIgnoreShadowAlpha = false;
  43. bool fDoAlphaAnimation = false;
  44. void onOnceBeforeDraw() override {
  45. fCirclePath.addCircle(0, 0, 50);
  46. fRectPath.addRect(SkRect::MakeXYWH(-100, -50, 200, 100));
  47. fRRPath.addRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(-100, -50, 200, 100), 4, 4));
  48. fFunkyRRPath.addRoundRect(SkRect::MakeXYWH(-50, -50, SK_Scalar1 * 100, SK_Scalar1 * 100),
  49. 40 * SK_Scalar1, 20 * SK_Scalar1,
  50. SkPath::kCW_Direction);
  51. fCubicPath.cubicTo(100 * SK_Scalar1, 50 * SK_Scalar1,
  52. 20 * SK_Scalar1, 100 * SK_Scalar1,
  53. 0 * SK_Scalar1, 0 * SK_Scalar1);
  54. fStarPath.moveTo(0.0f, -50.0f);
  55. fStarPath.lineTo(14.43f, -25.0f);
  56. fStarPath.lineTo(43.30f, -25.0f);
  57. fStarPath.lineTo(28.86f, 0.0f);
  58. fStarPath.lineTo(43.30f, 25.0f);
  59. fStarPath.lineTo(14.43f, 25.0f);
  60. fStarPath.lineTo(0.0f, 50.0f);
  61. fStarPath.lineTo(-14.43f, 25.0f);
  62. fStarPath.lineTo(-43.30f, 25.0f);
  63. fStarPath.lineTo(-28.86f, 0.0f);
  64. fStarPath.lineTo(-43.30f, -25.0f);
  65. fStarPath.lineTo(-14.43f, -25.0f);
  66. fSquareRRectPath.addRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(-50, -50, 100, 100),
  67. 10, 10));
  68. fWideRectPath.addRect(SkRect::MakeXYWH(0, 0, 630, 70));
  69. fWideOvalPath.addOval(SkRect::MakeXYWH(0, 0, 630, 70));
  70. fNotchPath.moveTo(0, 80);
  71. fNotchPath.arcTo(SkRect::MakeLTRB(-20, 80, 20, 120), -90, -90, false);
  72. fNotchPath.lineTo(-75, 100);
  73. fNotchPath.lineTo(-75, -100);
  74. fNotchPath.lineTo(75, -100);
  75. fNotchPath.lineTo(75, 100);
  76. fNotchPath.arcTo(SkRect::MakeLTRB(-20, 80, 20, 120), 0, -90, false);
  77. fTabPath.moveTo(-75, -100);
  78. fTabPath.lineTo(75, -100);
  79. fTabPath.lineTo(75, 100);
  80. fTabPath.arcTo(SkRect::MakeLTRB(-20, 80, 20, 120), 0, 90, false);
  81. fTabPath.arcTo(SkRect::MakeLTRB(-20, 80, 20, 120), 90, 90, false);
  82. fTabPath.lineTo(-75, 100);
  83. fLightPos = SkPoint3::Make(350, 0, 600);
  84. }
  85. SkString name() override { return SkString("AndroidShadows"); }
  86. bool onChar(SkUnichar uni) override {
  87. bool handled = false;
  88. switch (uni) {
  89. case 'W':
  90. fShowAmbient = !fShowAmbient;
  91. handled = true;
  92. break;
  93. case 'S':
  94. fShowSpot = !fShowSpot;
  95. handled = true;
  96. break;
  97. case 'T':
  98. fUseAlt = !fUseAlt;
  99. handled = true;
  100. break;
  101. case 'O':
  102. fShowObject = !fShowObject;
  103. handled = true;
  104. break;
  105. case 'N':
  106. fDoAlphaAnimation = !fDoAlphaAnimation;
  107. if (!fDoAlphaAnimation) {
  108. fAnimAlpha = 1;
  109. }
  110. handled = true;
  111. break;
  112. case '>':
  113. fZDelta += 0.5f;
  114. handled = true;
  115. break;
  116. case '<':
  117. fZDelta -= 0.5f;
  118. handled = true;
  119. break;
  120. case '?':
  121. fIgnoreShadowAlpha = !fIgnoreShadowAlpha;
  122. handled = true;
  123. break;
  124. default:
  125. break;
  126. }
  127. if (handled) {
  128. return true;
  129. }
  130. return false;
  131. }
  132. void drawShadowedPath(SkCanvas* canvas, const SkPath& path,
  133. const SkPoint3& zPlaneParams,
  134. const SkPaint& paint, SkScalar ambientAlpha,
  135. const SkPoint3& lightPos, SkScalar lightWidth, SkScalar spotAlpha) {
  136. if (fIgnoreShadowAlpha) {
  137. ambientAlpha = 1;
  138. spotAlpha = 1;
  139. }
  140. if (!fShowAmbient) {
  141. ambientAlpha = 0;
  142. }
  143. if (!fShowSpot) {
  144. spotAlpha = 0;
  145. }
  146. uint32_t flags = 0;
  147. if (fUseAlt) {
  148. flags |= SkShadowFlags::kGeometricOnly_ShadowFlag;
  149. }
  150. SkColor ambientColor = SkColorSetARGB(ambientAlpha * 255, 0, 0, 0);
  151. SkColor spotColor = SkColorSetARGB(spotAlpha * 255, 0, 0, 0);
  152. SkShadowUtils::DrawShadow(canvas, path, zPlaneParams, lightPos, lightWidth,
  153. ambientColor, spotColor, flags);
  154. if (fShowObject) {
  155. canvas->drawPath(path, paint);
  156. } else {
  157. SkPaint strokePaint;
  158. strokePaint.setColor(paint.getColor());
  159. strokePaint.setStyle(SkPaint::kStroke_Style);
  160. canvas->drawPath(path, strokePaint);
  161. }
  162. }
  163. void onDrawContent(SkCanvas* canvas) override {
  164. canvas->drawColor(0xFFDDDDDD);
  165. const SkScalar kLightWidth = 800;
  166. const SkScalar kAmbientAlpha = 0.039f;
  167. const SkScalar kSpotAlpha = 0.19f;
  168. SkPaint paint;
  169. paint.setAntiAlias(true);
  170. SkPoint3 lightPos = fLightPos;
  171. SkPoint3 zPlaneParams = SkPoint3::Make(0, 0, 0);
  172. paint.setColor(SK_ColorWHITE);
  173. canvas->translate(200, 90);
  174. zPlaneParams.fZ = SkTMax(1.0f, 2 + fZDelta);
  175. this->drawShadowedPath(canvas, fRRPath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha,
  176. lightPos, kLightWidth, fAnimAlpha*kSpotAlpha);
  177. paint.setColor(SK_ColorRED);
  178. canvas->translate(250, 0);
  179. zPlaneParams.fZ = SkTMax(1.0f, 8 + fZDelta);
  180. this->drawShadowedPath(canvas, fRectPath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha,
  181. lightPos, kLightWidth, fAnimAlpha*kSpotAlpha);
  182. paint.setColor(SK_ColorBLUE);
  183. canvas->translate(-250, 110);
  184. zPlaneParams.fZ = SkTMax(1.0f, 12 + fZDelta);
  185. this->drawShadowedPath(canvas, fCirclePath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha,
  186. lightPos, kLightWidth, fAnimAlpha*0.5f);
  187. paint.setColor(SK_ColorGREEN);
  188. canvas->translate(250, 0);
  189. zPlaneParams.fZ = SkTMax(1.0f, 64 + fZDelta);
  190. this->drawShadowedPath(canvas, fRRPath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha,
  191. lightPos, kLightWidth, fAnimAlpha*kSpotAlpha);
  192. paint.setColor(SK_ColorYELLOW);
  193. canvas->translate(-250, 110);
  194. zPlaneParams.fZ = SkTMax(1.0f, 8 + fZDelta);
  195. this->drawShadowedPath(canvas, fFunkyRRPath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha,
  196. lightPos, kLightWidth, fAnimAlpha*kSpotAlpha);
  197. paint.setColor(SK_ColorCYAN);
  198. canvas->translate(250, 0);
  199. zPlaneParams.fZ = SkTMax(1.0f, 16 + fZDelta);
  200. this->drawShadowedPath(canvas, fCubicPath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha,
  201. lightPos, kLightWidth, fAnimAlpha*kSpotAlpha);
  202. paint.setColor(SK_ColorWHITE);
  203. canvas->translate(250, -180);
  204. zPlaneParams.fZ = SkTMax(1.0f, 8 + fZDelta);
  205. this->drawShadowedPath(canvas, fStarPath, zPlaneParams, paint,
  206. kAmbientAlpha, lightPos, kLightWidth, kSpotAlpha);
  207. paint.setColor(SK_ColorWHITE);
  208. canvas->translate(150, 0);
  209. zPlaneParams.fZ = SkTMax(1.0f, 2 + fZDelta);
  210. this->drawShadowedPath(canvas, fNotchPath, zPlaneParams, paint,
  211. kAmbientAlpha, lightPos, kLightWidth, kSpotAlpha);
  212. paint.setColor(SK_ColorWHITE);
  213. canvas->translate(200, 0);
  214. zPlaneParams.fZ = SkTMax(1.0f, 16 + fZDelta);
  215. this->drawShadowedPath(canvas, fTabPath, zPlaneParams, paint,
  216. kAmbientAlpha, lightPos, kLightWidth, kSpotAlpha);
  217. // circular reveal
  218. SkPath tmpPath;
  219. SkPath tmpClipPath;
  220. tmpClipPath.addCircle(fAnimTranslate, 0, 60);
  221. Op(fSquareRRectPath, tmpClipPath, kIntersect_SkPathOp, &tmpPath);
  222. paint.setColor(SK_ColorMAGENTA);
  223. canvas->translate(-725, 240);
  224. zPlaneParams.fZ = SkTMax(1.0f, 32 + fZDelta);
  225. this->drawShadowedPath(canvas, tmpPath, zPlaneParams, paint, .1f,
  226. lightPos, kLightWidth, .5f);
  227. // path ops bug
  228. SkPath tmpClipPathBug;
  229. tmpClipPathBug.addCircle(88.0344925f, 0, 60);
  230. Op(fSquareRRectPath, tmpClipPathBug, kIntersect_SkPathOp, &tmpPath);
  231. canvas->translate(250, 0);
  232. zPlaneParams.fZ = SkTMax(1.0f, 32 + fZDelta);
  233. this->drawShadowedPath(canvas, tmpPath, zPlaneParams, paint, .1f,
  234. lightPos, kLightWidth, .5f);
  235. // perspective paths
  236. SkPoint pivot = SkPoint::Make(fWideRectPath.getBounds().width()/2,
  237. fWideRectPath.getBounds().height()/2);
  238. SkPoint translate = SkPoint::Make(100, 450);
  239. paint.setColor(SK_ColorWHITE);
  240. Sk3DView view;
  241. view.save();
  242. view.rotateX(fAnimAngle);
  243. SkMatrix persp;
  244. view.getMatrix(&persp);
  245. persp.preTranslate(-pivot.fX, -pivot.fY);
  246. persp.postTranslate(pivot.fX + translate.fX, pivot.fY + translate.fY);
  247. canvas->setMatrix(persp);
  248. SkScalar radians = SkDegreesToRadians(fAnimAngle);
  249. zPlaneParams = SkPoint3::Make(0,
  250. SkScalarSin(radians),
  251. SkTMax(1.0f, 16 + fZDelta) - SkScalarSin(radians)*pivot.fY);
  252. this->drawShadowedPath(canvas, fWideRectPath, zPlaneParams, paint, .1f,
  253. lightPos, kLightWidth, .5f);
  254. pivot = SkPoint::Make(fWideOvalPath.getBounds().width() / 2,
  255. fWideOvalPath.getBounds().height() / 2);
  256. translate = SkPoint::Make(100, 600);
  257. view.restore();
  258. view.save();
  259. view.rotateY(fAnimAngle);
  260. view.getMatrix(&persp);
  261. persp.preTranslate(-pivot.fX, -pivot.fY);
  262. persp.postTranslate(pivot.fX + translate.fX, pivot.fY + translate.fY);
  263. canvas->setMatrix(persp);
  264. zPlaneParams = SkPoint3::Make(-SkScalarSin(radians),
  265. 0,
  266. SkTMax(1.0f, 32 + fZDelta) + SkScalarSin(radians)*pivot.fX);
  267. this->drawShadowedPath(canvas, fWideOvalPath, zPlaneParams, paint, .1f,
  268. lightPos, kLightWidth, .5f);
  269. pivot = SkPoint::Make(fStarPath.getBounds().width() / 2,
  270. fStarPath.getBounds().height() / 2);
  271. translate = SkPoint::Make(700, 250);
  272. view.restore();
  273. view.rotateY(fAnimAngle);
  274. view.getMatrix(&persp);
  275. persp.preTranslate(-pivot.fX, -pivot.fY);
  276. persp.postTranslate(pivot.fX + translate.fX, pivot.fY + translate.fY);
  277. canvas->setMatrix(persp);
  278. zPlaneParams = SkPoint3::Make(-SkScalarSin(radians),
  279. 0,
  280. SkTMax(1.0f, 8 + fZDelta) + SkScalarSin(radians)*pivot.fX);
  281. this->drawShadowedPath(canvas, fStarPath, zPlaneParams, paint, .1f,
  282. lightPos, kLightWidth, .5f);
  283. }
  284. bool onAnimate(double nanos) override {
  285. fAnimTranslate = TimeUtils::PingPong(1e-9 * nanos, 30, 0, 125, -125);
  286. fAnimAngle = TimeUtils::PingPong(1e-9 * nanos, 15, 0, 0, 20);
  287. if (fDoAlphaAnimation) {
  288. fAnimAlpha = TimeUtils::PingPong(1e-9 * nanos, 5, 0, 1, 0);
  289. }
  290. return true;
  291. }
  292. private:
  293. typedef Sample INHERITED;
  294. };
  295. //////////////////////////////////////////////////////////////////////////////
  296. DEF_SAMPLE( return new ShadowsView(); )