pictureshader.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  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/SkMatrix.h"
  12. #include "include/core/SkPaint.h"
  13. #include "include/core/SkPicture.h"
  14. #include "include/core/SkPictureRecorder.h"
  15. #include "include/core/SkPoint.h"
  16. #include "include/core/SkRect.h"
  17. #include "include/core/SkRefCnt.h"
  18. #include "include/core/SkScalar.h"
  19. #include "include/core/SkShader.h"
  20. #include "include/core/SkSize.h"
  21. #include "include/core/SkString.h"
  22. #include "include/core/SkTileMode.h"
  23. #include "include/core/SkTypes.h"
  24. #include "tools/ToolUtils.h"
  25. static struct {
  26. SkTileMode tmx;
  27. SkTileMode tmy;
  28. } kTileConfigs[] = {
  29. { SkTileMode::kRepeat, SkTileMode::kRepeat },
  30. { SkTileMode::kRepeat, SkTileMode::kClamp },
  31. { SkTileMode::kMirror, SkTileMode::kRepeat },
  32. };
  33. class PictureShaderGM : public skiagm::GM {
  34. public:
  35. PictureShaderGM(SkScalar tileSize, SkScalar sceneSize, bool useLocalMatrixWrapper = false)
  36. : fTileSize(tileSize)
  37. , fSceneSize(sceneSize)
  38. , fUseLocalMatrixWrapper(useLocalMatrixWrapper) {}
  39. protected:
  40. void onOnceBeforeDraw() override {
  41. // Build the picture.
  42. SkPictureRecorder recorder;
  43. SkCanvas* pictureCanvas = recorder.beginRecording(fTileSize, fTileSize, nullptr, 0);
  44. this->drawTile(pictureCanvas);
  45. fPicture = recorder.finishRecordingAsPicture();
  46. // Build a reference bitmap.
  47. fBitmap.allocN32Pixels(SkScalarCeilToInt(fTileSize), SkScalarCeilToInt(fTileSize));
  48. fBitmap.eraseColor(SK_ColorTRANSPARENT);
  49. SkCanvas bitmapCanvas(fBitmap);
  50. this->drawTile(&bitmapCanvas);
  51. }
  52. SkString onShortName() override {
  53. return SkStringPrintf("pictureshader%s", fUseLocalMatrixWrapper ? "_localwrapper" : "");
  54. }
  55. SkISize onISize() override {
  56. return SkISize::Make(1400, 1450);
  57. }
  58. void onDraw(SkCanvas* canvas) override {
  59. this->drawSceneColumn(canvas, SkPoint::Make(0, 0), 1, 1, 0);
  60. this->drawSceneColumn(canvas, SkPoint::Make(0, fSceneSize * 6.4f), 1, 2, 0);
  61. this->drawSceneColumn(canvas, SkPoint::Make(fSceneSize * 2.4f, 0), 1, 1, 1);
  62. this->drawSceneColumn(canvas, SkPoint::Make(fSceneSize * 2.4f, fSceneSize * 6.4f), 1, 1, 2);
  63. this->drawSceneColumn(canvas, SkPoint::Make(fSceneSize * 4.8f, 0), 2, 1, 0);
  64. this->drawSceneColumn(canvas, SkPoint::Make(fSceneSize * 9.6f, 0), 2, 2, 0);
  65. // One last custom row to exercise negative scaling
  66. SkMatrix ctm, localMatrix;
  67. ctm.setTranslate(fSceneSize * 2.1f, fSceneSize * 13.8f);
  68. ctm.preScale(-1, -1);
  69. localMatrix.setScale(2, 2);
  70. this->drawScene(canvas, ctm, localMatrix, 0);
  71. ctm.setTranslate(fSceneSize * 2.4f, fSceneSize * 12.8f);
  72. localMatrix.setScale(-1, -1);
  73. this->drawScene(canvas, ctm, localMatrix, 0);
  74. ctm.setTranslate(fSceneSize * 4.8f, fSceneSize * 12.3f);
  75. ctm.preScale(2, 2);
  76. this->drawScene(canvas, ctm, localMatrix, 0);
  77. ctm.setTranslate(fSceneSize * 13.8f, fSceneSize * 14.3f);
  78. ctm.preScale(-2, -2);
  79. localMatrix.setTranslate(fTileSize / 4, fTileSize / 4);
  80. localMatrix.preRotate(45);
  81. localMatrix.preScale(-2, -2);
  82. this->drawScene(canvas, ctm, localMatrix, 0);
  83. }
  84. private:
  85. void drawSceneColumn(SkCanvas* canvas, const SkPoint& pos, SkScalar scale, SkScalar localScale,
  86. unsigned tileMode) {
  87. SkMatrix ctm, localMatrix;
  88. ctm.setTranslate(pos.x(), pos.y());
  89. ctm.preScale(scale, scale);
  90. localMatrix.setScale(localScale, localScale);
  91. this->drawScene(canvas, ctm, localMatrix, tileMode);
  92. ctm.setTranslate(pos.x(), pos.y() + fSceneSize * 1.2f * scale);
  93. ctm.preScale(scale, scale);
  94. localMatrix.setTranslate(fTileSize / 4, fTileSize / 4);
  95. localMatrix.preScale(localScale, localScale);
  96. this->drawScene(canvas, ctm, localMatrix, tileMode);
  97. ctm.setTranslate(pos.x(), pos.y() + fSceneSize * 2.4f * scale);
  98. ctm.preScale(scale, scale);
  99. localMatrix.setRotate(45);
  100. localMatrix.preScale(localScale, localScale);
  101. this->drawScene(canvas, ctm, localMatrix, tileMode);
  102. ctm.setTranslate(pos.x(), pos.y() + fSceneSize * 3.6f * scale);
  103. ctm.preScale(scale, scale);
  104. localMatrix.setSkew(1, 0);
  105. localMatrix.preScale(localScale, localScale);
  106. this->drawScene(canvas, ctm, localMatrix, tileMode);
  107. ctm.setTranslate(pos.x(), pos.y() + fSceneSize * 4.8f * scale);
  108. ctm.preScale(scale, scale);
  109. localMatrix.setTranslate(fTileSize / 4, fTileSize / 4);
  110. localMatrix.preRotate(45);
  111. localMatrix.preScale(localScale, localScale);
  112. this->drawScene(canvas, ctm, localMatrix, tileMode);
  113. }
  114. void drawTile(SkCanvas* canvas) {
  115. SkPaint paint;
  116. paint.setColor(SK_ColorGREEN);
  117. paint.setStyle(SkPaint::kFill_Style);
  118. paint.setAntiAlias(true);
  119. canvas->drawCircle(fTileSize / 4, fTileSize / 4, fTileSize / 4, paint);
  120. canvas->drawRect(SkRect::MakeXYWH(fTileSize / 2, fTileSize / 2,
  121. fTileSize / 2, fTileSize / 2), paint);
  122. paint.setColor(SK_ColorRED);
  123. canvas->drawLine(fTileSize / 2, fTileSize * 1 / 3,
  124. fTileSize / 2, fTileSize * 2 / 3, paint);
  125. canvas->drawLine(fTileSize * 1 / 3, fTileSize / 2,
  126. fTileSize * 2 / 3, fTileSize / 2, paint);
  127. }
  128. void drawScene(SkCanvas* canvas, const SkMatrix& matrix, const SkMatrix& localMatrix,
  129. unsigned tileMode) {
  130. SkASSERT(tileMode < SK_ARRAY_COUNT(kTileConfigs));
  131. SkPaint paint;
  132. paint.setStyle(SkPaint::kFill_Style);
  133. paint.setColor(SK_ColorLTGRAY);
  134. canvas->save();
  135. canvas->concat(matrix);
  136. canvas->drawRect(SkRect::MakeWH(fSceneSize, fSceneSize), paint);
  137. canvas->drawRect(SkRect::MakeXYWH(fSceneSize * 1.1f, 0, fSceneSize, fSceneSize), paint);
  138. auto pictureShader = fPicture->makeShader(kTileConfigs[tileMode].tmx,
  139. kTileConfigs[tileMode].tmy,
  140. fUseLocalMatrixWrapper ? nullptr : &localMatrix,
  141. nullptr);
  142. paint.setShader(fUseLocalMatrixWrapper
  143. ? pictureShader->makeWithLocalMatrix(localMatrix)
  144. : pictureShader);
  145. canvas->drawRect(SkRect::MakeWH(fSceneSize, fSceneSize), paint);
  146. canvas->translate(fSceneSize * 1.1f, 0);
  147. auto bitmapShader = fBitmap.makeShader(
  148. kTileConfigs[tileMode].tmx,
  149. kTileConfigs[tileMode].tmy,
  150. fUseLocalMatrixWrapper
  151. ? nullptr : &localMatrix);
  152. paint.setShader(fUseLocalMatrixWrapper
  153. ? bitmapShader->makeWithLocalMatrix(localMatrix)
  154. : bitmapShader);
  155. canvas->drawRect(SkRect::MakeWH(fSceneSize, fSceneSize), paint);
  156. canvas->restore();
  157. }
  158. sk_sp<SkPicture> fPicture;
  159. SkBitmap fBitmap;
  160. SkScalar fTileSize;
  161. SkScalar fSceneSize;
  162. bool fUseLocalMatrixWrapper;
  163. typedef GM INHERITED;
  164. };
  165. DEF_GM(return new PictureShaderGM(50, 100);)
  166. DEF_GM(return new PictureShaderGM(50, 100, true);)
  167. DEF_SIMPLE_GM(tiled_picture_shader, canvas, 400, 400) {
  168. // https://code.google.com/p/skia/issues/detail?id=3398
  169. SkRect tile = SkRect::MakeWH(100, 100);
  170. SkPictureRecorder recorder;
  171. SkCanvas* c = recorder.beginRecording(tile);
  172. SkRect r = tile;
  173. r.inset(4, 4);
  174. SkPaint p;
  175. p.setColor(ToolUtils::color_to_565(0xFF303F9F)); // dark blue
  176. c->drawRect(r, p);
  177. p.setColor(ToolUtils::color_to_565(0xFFC5CAE9)); // light blue
  178. p.setStrokeWidth(10);
  179. c->drawLine(20, 20, 80, 80, p);
  180. sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
  181. p.setColor(ToolUtils::color_to_565(0xFF8BC34A)); // green
  182. canvas->drawPaint(p);
  183. canvas->clipRect(SkRect::MakeXYWH(0, 0, 400, 350));
  184. p.setColor(0xFFB6B6B6); // gray
  185. canvas->drawPaint(p);
  186. p.setShader(picture->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat));
  187. canvas->drawPaint(p);
  188. }