filterfastbounds.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. /*
  2. * Copyright 2014 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 "gm/gm.h"
  8. #include "include/core/SkBitmap.h"
  9. #include "include/core/SkCanvas.h"
  10. #include "include/core/SkColor.h"
  11. #include "include/core/SkFilterQuality.h"
  12. #include "include/core/SkImage.h"
  13. #include "include/core/SkImageFilter.h"
  14. #include "include/core/SkMatrix.h"
  15. #include "include/core/SkPaint.h"
  16. #include "include/core/SkPath.h"
  17. #include "include/core/SkPicture.h"
  18. #include "include/core/SkPictureRecorder.h"
  19. #include "include/core/SkPoint.h"
  20. #include "include/core/SkRRect.h"
  21. #include "include/core/SkRect.h"
  22. #include "include/core/SkRefCnt.h"
  23. #include "include/core/SkScalar.h"
  24. #include "include/core/SkSize.h"
  25. #include "include/core/SkString.h"
  26. #include "include/core/SkSurface.h"
  27. #include "include/core/SkTypes.h"
  28. #include "include/effects/SkBlurImageFilter.h"
  29. #include "include/effects/SkDropShadowImageFilter.h"
  30. #include "include/effects/SkImageSource.h"
  31. #include "include/effects/SkOffsetImageFilter.h"
  32. #include "include/effects/SkPictureImageFilter.h"
  33. #include "include/effects/SkTileImageFilter.h"
  34. #include "include/private/SkTArray.h"
  35. #include <utility>
  36. namespace skiagm {
  37. // Each method of this type must draw its geometry inside 'r' using 'p'
  38. typedef void(*drawMth)(SkCanvas* canvas, const SkRect& r, const SkPaint& p);
  39. static void draw_rect(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
  40. canvas->drawRect(r, p);
  41. }
  42. static void draw_oval(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
  43. canvas->drawOval(r, p);
  44. }
  45. static void draw_rrect(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
  46. SkScalar xRad = r.width() / 4.0f;
  47. SkScalar yRad = r.height() / 4.0f;
  48. SkRRect rr;
  49. rr.setRectXY(r, xRad, yRad);
  50. canvas->drawRRect(rr, p);
  51. }
  52. static void draw_drrect(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
  53. SkScalar xRad = r.width() / 4.0f;
  54. SkScalar yRad = r.height() / 4.0f;
  55. SkRRect outer;
  56. outer.setRectXY(r, xRad, yRad);
  57. SkRRect inner = outer;
  58. inner.inset(xRad, yRad);
  59. canvas->drawDRRect(outer, inner, p);
  60. }
  61. static void draw_path(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
  62. SkPath path;
  63. path.moveTo(r.fLeft, r.fTop);
  64. path.lineTo(r.fLeft, r.fBottom);
  65. path.lineTo(r.fRight, r.fBottom);
  66. path.close();
  67. canvas->drawPath(path, p);
  68. }
  69. static void draw_points(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
  70. SkPoint pts0[2] = { { r.fLeft, r.fTop }, { r.fRight, r.fBottom } };
  71. SkPoint pts1[2] = { { r.fLeft, r.fBottom }, { r.fRight, r.fTop } };
  72. canvas->drawPoints(SkCanvas::kLines_PointMode, 2, pts0, p);
  73. canvas->drawPoints(SkCanvas::kLines_PointMode, 2, pts1, p);
  74. }
  75. static void draw_bitmap(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
  76. SkBitmap bm;
  77. bm.allocN32Pixels(64, 64);
  78. SkCanvas temp(bm);
  79. temp.clear(SK_ColorMAGENTA);
  80. canvas->drawBitmapRect(bm, r, &p);
  81. }
  82. constexpr drawMth gDrawMthds[] = {
  83. draw_rect, draw_oval, draw_rrect, draw_drrect, draw_path, draw_points, draw_bitmap
  84. };
  85. static void add_paint(SkTArray<SkPaint>* paints, sk_sp<SkImageFilter> filter) {
  86. SkPaint& p = paints->push_back();
  87. p.setImageFilter(std::move(filter));
  88. SkASSERT(p.canComputeFastBounds());
  89. }
  90. // Create a selection of imagefilter-based paints to test
  91. static void create_paints(SkTArray<SkPaint>* paints, sk_sp<SkImageFilter> source) {
  92. {
  93. SkMatrix scale;
  94. scale.setScale(2.0f, 2.0f);
  95. sk_sp<SkImageFilter> scaleMIF(
  96. SkImageFilter::MakeMatrixFilter(scale, kLow_SkFilterQuality, source));
  97. add_paint(paints, std::move(scaleMIF));
  98. }
  99. {
  100. SkMatrix rot;
  101. rot.setRotate(-33.3f);
  102. sk_sp<SkImageFilter> rotMIF(
  103. SkImageFilter::MakeMatrixFilter(rot, kLow_SkFilterQuality, source));
  104. add_paint(paints, std::move(rotMIF));
  105. }
  106. {
  107. SkRect src = SkRect::MakeXYWH(20, 20, 10, 10);
  108. SkRect dst = SkRect::MakeXYWH(30, 30, 30, 30);
  109. sk_sp<SkImageFilter> tileIF(SkTileImageFilter::Make(src, dst, nullptr));
  110. add_paint(paints, std::move(tileIF));
  111. }
  112. {
  113. constexpr SkDropShadowImageFilter::ShadowMode kBoth =
  114. SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode;
  115. sk_sp<SkImageFilter> dsif(SkDropShadowImageFilter::Make(10.0f, 10.0f,
  116. 3.0f, 3.0f,
  117. SK_ColorRED, kBoth,
  118. source));
  119. add_paint(paints, std::move(dsif));
  120. }
  121. {
  122. sk_sp<SkImageFilter> dsif(
  123. SkDropShadowImageFilter::Make(27.0f, 27.0f,
  124. 3.0f, 3.0f,
  125. SK_ColorRED,
  126. SkDropShadowImageFilter::kDrawShadowOnly_ShadowMode,
  127. source));
  128. add_paint(paints, std::move(dsif));
  129. }
  130. add_paint(paints, SkBlurImageFilter::Make(3, 3, source));
  131. add_paint(paints, SkOffsetImageFilter::Make(15, 15, source));
  132. }
  133. // This GM visualizes the fast bounds for various combinations of geometry
  134. // and image filter
  135. class ImageFilterFastBoundGM : public GM {
  136. public:
  137. ImageFilterFastBoundGM() {
  138. this->setBGColor(0xFFCCCCCC);
  139. }
  140. protected:
  141. static constexpr int kTileWidth = 100;
  142. static constexpr int kTileHeight = 100;
  143. static constexpr int kNumVertTiles = 7;
  144. static constexpr int kNumXtraCols = 2;
  145. SkString onShortName() override { return SkString("filterfastbounds"); }
  146. SkISize onISize() override {
  147. return SkISize::Make((SK_ARRAY_COUNT(gDrawMthds) + kNumXtraCols) * kTileWidth,
  148. kNumVertTiles * kTileHeight);
  149. }
  150. static void draw_geom_with_paint(drawMth draw, const SkIPoint& off,
  151. SkCanvas* canvas, const SkPaint& p) {
  152. SkPaint redStroked;
  153. redStroked.setColor(SK_ColorRED);
  154. redStroked.setStyle(SkPaint::kStroke_Style);
  155. SkPaint blueStroked;
  156. blueStroked.setColor(SK_ColorBLUE);
  157. blueStroked.setStyle(SkPaint::kStroke_Style);
  158. const SkRect r = SkRect::MakeLTRB(20, 20, 30, 30);
  159. SkRect storage;
  160. canvas->save();
  161. canvas->translate(SkIntToScalar(off.fX), SkIntToScalar(off.fY));
  162. canvas->scale(1.5f, 1.5f);
  163. const SkRect& fastBound = p.computeFastBounds(r, &storage);
  164. canvas->save();
  165. canvas->clipRect(fastBound);
  166. (*draw)(canvas, r, p);
  167. canvas->restore();
  168. canvas->drawRect(r, redStroked);
  169. canvas->drawRect(fastBound, blueStroked);
  170. canvas->restore();
  171. }
  172. static void draw_savelayer_with_paint(const SkIPoint& off,
  173. SkCanvas* canvas,
  174. const SkPaint& p) {
  175. SkPaint redStroked;
  176. redStroked.setColor(SK_ColorRED);
  177. redStroked.setStyle(SkPaint::kStroke_Style);
  178. SkPaint blueStroked;
  179. blueStroked.setColor(SK_ColorBLUE);
  180. blueStroked.setStyle(SkPaint::kStroke_Style);
  181. const SkRect bounds = SkRect::MakeWH(10, 10);
  182. SkRect storage;
  183. canvas->save();
  184. canvas->translate(30, 30);
  185. canvas->translate(SkIntToScalar(off.fX), SkIntToScalar(off.fY));
  186. canvas->scale(1.5f, 1.5f);
  187. const SkRect& fastBound = p.computeFastBounds(bounds, &storage);
  188. canvas->saveLayer(&fastBound, &p);
  189. canvas->restore();
  190. canvas->drawRect(bounds, redStroked);
  191. canvas->drawRect(fastBound, blueStroked);
  192. canvas->restore();
  193. }
  194. void onDraw(SkCanvas* canvas) override {
  195. SkPaint blackFill;
  196. //-----------
  197. // Normal paints (no source)
  198. SkTArray<SkPaint> paints;
  199. create_paints(&paints, nullptr);
  200. //-----------
  201. // Paints with a PictureImageFilter as a source
  202. sk_sp<SkPicture> pic;
  203. {
  204. SkPictureRecorder rec;
  205. SkCanvas* c = rec.beginRecording(10, 10);
  206. c->drawRect(SkRect::MakeWH(10, 10), blackFill);
  207. pic = rec.finishRecordingAsPicture();
  208. }
  209. SkTArray<SkPaint> pifPaints;
  210. create_paints(&pifPaints, SkPictureImageFilter::Make(pic));
  211. //-----------
  212. // Paints with a SkImageSource as a source
  213. auto surface(SkSurface::MakeRasterN32Premul(10, 10));
  214. {
  215. SkPaint p;
  216. SkCanvas* temp = surface->getCanvas();
  217. temp->clear(SK_ColorYELLOW);
  218. p.setColor(SK_ColorBLUE);
  219. temp->drawRect(SkRect::MakeLTRB(5, 5, 10, 10), p);
  220. p.setColor(SK_ColorGREEN);
  221. temp->drawRect(SkRect::MakeLTRB(5, 0, 10, 5), p);
  222. }
  223. sk_sp<SkImage> image(surface->makeImageSnapshot());
  224. sk_sp<SkImageFilter> imageSource(SkImageSource::Make(std::move(image)));
  225. SkTArray<SkPaint> bmsPaints;
  226. create_paints(&bmsPaints, std::move(imageSource));
  227. //-----------
  228. SkASSERT(paints.count() == kNumVertTiles);
  229. SkASSERT(paints.count() == pifPaints.count());
  230. SkASSERT(paints.count() == bmsPaints.count());
  231. // horizontal separators
  232. for (int i = 1; i < paints.count(); ++i) {
  233. canvas->drawLine(0,
  234. i*SkIntToScalar(kTileHeight),
  235. SkIntToScalar((SK_ARRAY_COUNT(gDrawMthds) + kNumXtraCols)*kTileWidth),
  236. i*SkIntToScalar(kTileHeight),
  237. blackFill);
  238. }
  239. // vertical separators
  240. for (int i = 0; i < (int)SK_ARRAY_COUNT(gDrawMthds) + kNumXtraCols; ++i) {
  241. canvas->drawLine(SkIntToScalar(i * kTileWidth),
  242. 0,
  243. SkIntToScalar(i * kTileWidth),
  244. SkIntToScalar(paints.count() * kTileWidth),
  245. blackFill);
  246. }
  247. // A column of saveLayers with PictureImageFilters
  248. for (int i = 0; i < pifPaints.count(); ++i) {
  249. draw_savelayer_with_paint(SkIPoint::Make(0, i*kTileHeight),
  250. canvas, pifPaints[i]);
  251. }
  252. // A column of saveLayers with BitmapSources
  253. for (int i = 0; i < pifPaints.count(); ++i) {
  254. draw_savelayer_with_paint(SkIPoint::Make(kTileWidth, i*kTileHeight),
  255. canvas, bmsPaints[i]);
  256. }
  257. // Multiple columns with different geometry
  258. for (int i = 0; i < (int)SK_ARRAY_COUNT(gDrawMthds); ++i) {
  259. for (int j = 0; j < paints.count(); ++j) {
  260. draw_geom_with_paint(*gDrawMthds[i],
  261. SkIPoint::Make((i+kNumXtraCols) * kTileWidth, j*kTileHeight),
  262. canvas, paints[j]);
  263. }
  264. }
  265. }
  266. private:
  267. typedef GM INHERITED;
  268. };
  269. //////////////////////////////////////////////////////////////////////////////
  270. DEF_GM(return new ImageFilterFastBoundGM;)
  271. }