bitmaprect.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. /*
  2. * Copyright 2011 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/SkBlendMode.h"
  10. #include "include/core/SkCanvas.h"
  11. #include "include/core/SkColor.h"
  12. #include "include/core/SkPaint.h"
  13. #include "include/core/SkPoint.h"
  14. #include "include/core/SkRect.h"
  15. #include "include/core/SkShader.h"
  16. #include "include/core/SkSize.h"
  17. #include "include/core/SkString.h"
  18. #include "include/core/SkTileMode.h"
  19. #include "include/core/SkTypes.h"
  20. #include "include/effects/SkGradientShader.h"
  21. static void make_bitmap(SkBitmap* bitmap) {
  22. bitmap->allocN32Pixels(64, 64);
  23. SkCanvas canvas(*bitmap);
  24. canvas.drawColor(SK_ColorRED);
  25. SkPaint paint;
  26. paint.setAntiAlias(true);
  27. const SkPoint pts[] = { { 0, 0 }, { 64, 64 } };
  28. const SkColor colors[] = { SK_ColorWHITE, SK_ColorBLUE };
  29. paint.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkTileMode::kClamp));
  30. canvas.drawCircle(32, 32, 32, paint);
  31. }
  32. class DrawBitmapRect2 : public skiagm::GM {
  33. bool fUseIRect;
  34. public:
  35. DrawBitmapRect2(bool useIRect) : fUseIRect(useIRect) {
  36. }
  37. protected:
  38. SkString onShortName() override {
  39. SkString str;
  40. str.printf("bitmaprect_%s", fUseIRect ? "i" : "s");
  41. return str;
  42. }
  43. SkISize onISize() override {
  44. return SkISize::Make(640, 480);
  45. }
  46. void onDraw(SkCanvas* canvas) override {
  47. canvas->drawColor(0xFFCCCCCC);
  48. const SkIRect src[] = {
  49. { 0, 0, 32, 32 },
  50. { 0, 0, 80, 80 },
  51. { 32, 32, 96, 96 },
  52. { -32, -32, 32, 32, }
  53. };
  54. SkPaint paint;
  55. paint.setStyle(SkPaint::kStroke_Style);
  56. SkBitmap bitmap;
  57. make_bitmap(&bitmap);
  58. SkRect dstR = { 0, 200, 128, 380 };
  59. canvas->translate(16, 40);
  60. for (size_t i = 0; i < SK_ARRAY_COUNT(src); i++) {
  61. SkRect srcR;
  62. srcR.set(src[i]);
  63. canvas->drawBitmap(bitmap, 0, 0, &paint);
  64. if (!fUseIRect) {
  65. canvas->drawBitmapRect(bitmap, srcR, dstR, &paint,
  66. SkCanvas::kStrict_SrcRectConstraint);
  67. } else {
  68. canvas->drawBitmapRect(bitmap, src[i], dstR, &paint);
  69. }
  70. canvas->drawRect(dstR, paint);
  71. canvas->drawRect(srcR, paint);
  72. canvas->translate(160, 0);
  73. }
  74. }
  75. private:
  76. typedef skiagm::GM INHERITED;
  77. };
  78. //////////////////////////////////////////////////////////////////////////////
  79. static void make_3x3_bitmap(SkBitmap* bitmap) {
  80. const int xSize = 3;
  81. const int ySize = 3;
  82. const SkColor textureData[xSize][ySize] = {
  83. { SK_ColorRED, SK_ColorWHITE, SK_ColorBLUE },
  84. { SK_ColorGREEN, SK_ColorBLACK, SK_ColorCYAN },
  85. { SK_ColorYELLOW, SK_ColorGRAY, SK_ColorMAGENTA }
  86. };
  87. bitmap->allocN32Pixels(xSize, ySize, true);
  88. SkCanvas canvas(*bitmap);
  89. SkPaint paint;
  90. for (int y = 0; y < ySize; y++) {
  91. for (int x = 0; x < xSize; x++) {
  92. paint.setColor(textureData[x][y]);
  93. canvas.drawIRect(SkIRect::MakeXYWH(x, y, 1, 1), paint);
  94. }
  95. }
  96. }
  97. // This GM attempts to make visible any issues drawBitmapRect may have
  98. // with partial source rects. In this case the eight pixels on the border
  99. // should be half the width/height of the central pixel, i.e.:
  100. // __|____|__
  101. // | |
  102. // __|____|__
  103. // | |
  104. class DrawBitmapRect3 : public skiagm::GM {
  105. public:
  106. DrawBitmapRect3() {
  107. this->setBGColor(SK_ColorBLACK);
  108. }
  109. protected:
  110. SkString onShortName() override {
  111. SkString str;
  112. str.printf("3x3bitmaprect");
  113. return str;
  114. }
  115. SkISize onISize() override {
  116. return SkISize::Make(640, 480);
  117. }
  118. void onDraw(SkCanvas* canvas) override {
  119. SkBitmap bitmap;
  120. make_3x3_bitmap(&bitmap);
  121. SkRect srcR = { 0.5f, 0.5f, 2.5f, 2.5f };
  122. SkRect dstR = { 100, 100, 300, 200 };
  123. canvas->drawBitmapRect(bitmap, srcR, dstR, nullptr, SkCanvas::kStrict_SrcRectConstraint);
  124. }
  125. private:
  126. typedef skiagm::GM INHERITED;
  127. };
  128. //////////////////////////////////////////////////////////////////////////////
  129. static void make_big_bitmap(SkBitmap* bitmap) {
  130. constexpr int gXSize = 4096;
  131. constexpr int gYSize = 4096;
  132. constexpr int gBorderWidth = 10;
  133. bitmap->allocN32Pixels(gXSize, gYSize);
  134. for (int y = 0; y < gYSize; ++y) {
  135. for (int x = 0; x < gXSize; ++x) {
  136. if (x <= gBorderWidth || x >= gXSize-gBorderWidth ||
  137. y <= gBorderWidth || y >= gYSize-gBorderWidth) {
  138. *bitmap->getAddr32(x, y) = SkPreMultiplyColor(0x88FFFFFF);
  139. } else {
  140. *bitmap->getAddr32(x, y) = SkPreMultiplyColor(0x88FF0000);
  141. }
  142. }
  143. }
  144. }
  145. // This GM attempts to reveal any issues we may have when the GPU has to
  146. // break up a large texture in order to draw it. The XOR transfer mode will
  147. // create stripes in the image if there is imprecision in the destination
  148. // tile placement.
  149. class DrawBitmapRect4 : public skiagm::GM {
  150. bool fUseIRect;
  151. SkBitmap fBigBitmap;
  152. public:
  153. DrawBitmapRect4(bool useIRect) : fUseIRect(useIRect) {
  154. this->setBGColor(0x88444444);
  155. }
  156. protected:
  157. SkString onShortName() override {
  158. SkString str;
  159. str.printf("bigbitmaprect_%s", fUseIRect ? "i" : "s");
  160. return str;
  161. }
  162. SkISize onISize() override {
  163. return SkISize::Make(640, 480);
  164. }
  165. void onOnceBeforeDraw() override {
  166. make_big_bitmap(&fBigBitmap);
  167. }
  168. void onDraw(SkCanvas* canvas) override {
  169. SkPaint paint;
  170. paint.setAlpha(128);
  171. paint.setBlendMode(SkBlendMode::kXor);
  172. SkRect srcR1 = { 0.0f, 0.0f, 4096.0f, 2040.0f };
  173. SkRect dstR1 = { 10.1f, 10.1f, 629.9f, 400.9f };
  174. SkRect srcR2 = { 4085.0f, 10.0f, 4087.0f, 12.0f };
  175. SkRect dstR2 = { 10, 410, 30, 430 };
  176. if (!fUseIRect) {
  177. canvas->drawBitmapRect(fBigBitmap, srcR1, dstR1, &paint,
  178. SkCanvas::kStrict_SrcRectConstraint);
  179. canvas->drawBitmapRect(fBigBitmap, srcR2, dstR2, &paint,
  180. SkCanvas::kStrict_SrcRectConstraint);
  181. } else {
  182. canvas->drawBitmapRect(fBigBitmap, srcR1.roundOut(), dstR1, &paint);
  183. canvas->drawBitmapRect(fBigBitmap, srcR2.roundOut(), dstR2, &paint);
  184. }
  185. }
  186. private:
  187. typedef skiagm::GM INHERITED;
  188. };
  189. class BitmapRectRounding : public skiagm::GM {
  190. SkBitmap fBM;
  191. public:
  192. BitmapRectRounding() {}
  193. protected:
  194. SkString onShortName() override {
  195. SkString str;
  196. str.printf("bitmaprect_rounding");
  197. return str;
  198. }
  199. SkISize onISize() override {
  200. return SkISize::Make(640, 480);
  201. }
  202. void onOnceBeforeDraw() override {
  203. fBM.allocN32Pixels(10, 10);
  204. fBM.eraseColor(SK_ColorBLUE);
  205. }
  206. // This choice of coordinates and matrix land the bottom edge of the clip (and bitmap dst)
  207. // at exactly 1/2 pixel boundary. However, drawBitmapRect may lose precision along the way.
  208. // If it does, we may see a red-line at the bottom, instead of the bitmap exactly matching
  209. // the clip (in which case we should see all blue).
  210. // The correct image should be all blue.
  211. void onDraw(SkCanvas* canvas) override {
  212. SkPaint paint;
  213. paint.setColor(SK_ColorRED);
  214. const SkRect r = SkRect::MakeXYWH(1, 1, 110, 114);
  215. canvas->scale(0.9f, 0.9f);
  216. // the drawRect shows the same problem as clipRect(r) followed by drawcolor(red)
  217. canvas->drawRect(r, paint);
  218. canvas->drawBitmapRect(fBM, r, nullptr);
  219. }
  220. private:
  221. typedef skiagm::GM INHERITED;
  222. };
  223. DEF_GM( return new BitmapRectRounding; )
  224. //////////////////////////////////////////////////////////////////////////////
  225. DEF_GM( return new DrawBitmapRect2(false); )
  226. DEF_GM( return new DrawBitmapRect2(true); )
  227. DEF_GM( return new DrawBitmapRect3(); )
  228. #ifndef SK_BUILD_FOR_ANDROID
  229. DEF_GM( return new DrawBitmapRect4(false); )
  230. DEF_GM( return new DrawBitmapRect4(true); )
  231. #endif