xfermodes3.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /*
  2. * Copyright 2013 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/SkColorPriv.h"
  13. #include "include/core/SkColorSpace.h"
  14. #include "include/core/SkFont.h"
  15. #include "include/core/SkImageInfo.h"
  16. #include "include/core/SkMatrix.h"
  17. #include "include/core/SkPaint.h"
  18. #include "include/core/SkPoint.h"
  19. #include "include/core/SkRect.h"
  20. #include "include/core/SkRefCnt.h"
  21. #include "include/core/SkScalar.h"
  22. #include "include/core/SkShader.h"
  23. #include "include/core/SkSize.h"
  24. #include "include/core/SkString.h"
  25. #include "include/core/SkSurface.h"
  26. #include "include/core/SkTileMode.h"
  27. #include "include/core/SkTypeface.h"
  28. #include "include/core/SkTypes.h"
  29. #include "include/effects/SkGradientShader.h"
  30. #include "tools/ToolUtils.h"
  31. #include <string.h>
  32. namespace skiagm {
  33. /**
  34. * This tests drawing device-covering rects with solid colors and bitmap shaders over a
  35. * checkerboard background using different xfermodes.
  36. */
  37. class Xfermodes3GM : public GM {
  38. public:
  39. Xfermodes3GM() { this->setBGColor(ToolUtils::color_to_565(0xFF70D0E0)); }
  40. protected:
  41. SkString onShortName() override {
  42. return SkString("xfermodes3");
  43. }
  44. SkISize onISize() override {
  45. return SkISize::Make(630, 1215);
  46. }
  47. void onDraw(SkCanvas* canvas) override {
  48. canvas->translate(SkIntToScalar(10), SkIntToScalar(20));
  49. SkFont font(ToolUtils::create_portable_typeface());
  50. SkPaint labelP;
  51. constexpr SkColor kSolidColors[] = {
  52. SK_ColorTRANSPARENT,
  53. SK_ColorBLUE,
  54. 0x80808000
  55. };
  56. constexpr SkColor kBmpAlphas[] = {
  57. 0xff,
  58. 0x80,
  59. };
  60. auto tempSurface(this->makeTempSurface(canvas, kSize, kSize));
  61. int test = 0;
  62. int x = 0, y = 0;
  63. constexpr struct { SkPaint::Style fStyle; SkScalar fWidth; } kStrokes[] = {
  64. {SkPaint::kFill_Style, 0},
  65. {SkPaint::kStroke_Style, SkIntToScalar(kSize) / 2},
  66. };
  67. for (size_t s = 0; s < SK_ARRAY_COUNT(kStrokes); ++s) {
  68. for (size_t m = 0; m <= (size_t)SkBlendMode::kLastMode; ++m) {
  69. SkBlendMode mode = static_cast<SkBlendMode>(m);
  70. canvas->drawString(SkBlendMode_Name(mode),
  71. SkIntToScalar(x),
  72. SkIntToScalar(y + kSize + 3) + font.getSize(),
  73. font, labelP);
  74. for (size_t c = 0; c < SK_ARRAY_COUNT(kSolidColors); ++c) {
  75. SkPaint modePaint;
  76. modePaint.setBlendMode(mode);
  77. modePaint.setColor(kSolidColors[c]);
  78. modePaint.setStyle(kStrokes[s].fStyle);
  79. modePaint.setStrokeWidth(kStrokes[s].fWidth);
  80. this->drawMode(canvas, x, y, kSize, kSize, modePaint, tempSurface.get());
  81. ++test;
  82. x += kSize + 10;
  83. if (!(test % kTestsPerRow)) {
  84. x = 0;
  85. y += kSize + 30;
  86. }
  87. }
  88. for (size_t a = 0; a < SK_ARRAY_COUNT(kBmpAlphas); ++a) {
  89. SkPaint modePaint;
  90. modePaint.setBlendMode(mode);
  91. modePaint.setAlpha(kBmpAlphas[a]);
  92. modePaint.setShader(fBmpShader);
  93. modePaint.setStyle(kStrokes[s].fStyle);
  94. modePaint.setStrokeWidth(kStrokes[s].fWidth);
  95. this->drawMode(canvas, x, y, kSize, kSize, modePaint, tempSurface.get());
  96. ++test;
  97. x += kSize + 10;
  98. if (!(test % kTestsPerRow)) {
  99. x = 0;
  100. y += kSize + 30;
  101. }
  102. }
  103. }
  104. }
  105. }
  106. private:
  107. /**
  108. * GrContext has optimizations around full rendertarget draws that can be replaced with clears.
  109. * We are trying to test those. We could use saveLayer() to create small SkGpuDevices but
  110. * saveLayer() uses the texture cache. This means that the actual render target may be larger
  111. * than the layer. Because the clip will contain the layer's bounds, no draws will be full-RT.
  112. * So explicitly create a temporary canvas with dimensions exactly the layer size.
  113. */
  114. sk_sp<SkSurface> makeTempSurface(SkCanvas* baseCanvas, int w, int h) {
  115. SkImageInfo baseInfo = baseCanvas->imageInfo();
  116. SkImageInfo info = SkImageInfo::Make(w, h, baseInfo.colorType(), baseInfo.alphaType(),
  117. baseInfo.refColorSpace());
  118. return baseCanvas->makeSurface(info);
  119. }
  120. void drawMode(SkCanvas* canvas,
  121. int x, int y, int w, int h,
  122. const SkPaint& modePaint, SkSurface* surface) {
  123. canvas->save();
  124. canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
  125. SkRect r = SkRect::MakeWH(SkIntToScalar(w), SkIntToScalar(h));
  126. SkCanvas* modeCanvas;
  127. if (nullptr == surface) {
  128. canvas->saveLayer(&r, nullptr);
  129. canvas->clipRect(r);
  130. modeCanvas = canvas;
  131. } else {
  132. modeCanvas = surface->getCanvas();
  133. }
  134. SkPaint bgPaint;
  135. bgPaint.setAntiAlias(false);
  136. bgPaint.setShader(fBGShader);
  137. modeCanvas->drawRect(r, bgPaint);
  138. modeCanvas->drawRect(r, modePaint);
  139. modeCanvas = nullptr;
  140. if (nullptr == surface) {
  141. canvas->restore();
  142. } else {
  143. surface->draw(canvas, 0, 0, nullptr);
  144. }
  145. r.inset(-SK_ScalarHalf, -SK_ScalarHalf);
  146. SkPaint borderPaint;
  147. borderPaint.setStyle(SkPaint::kStroke_Style);
  148. canvas->drawRect(r, borderPaint);
  149. canvas->restore();
  150. }
  151. void onOnceBeforeDraw() override {
  152. const uint32_t kCheckData[] = {
  153. SkPackARGB32(0xFF, 0x42, 0x41, 0x42),
  154. SkPackARGB32(0xFF, 0xD6, 0xD3, 0xD6),
  155. SkPackARGB32(0xFF, 0xD6, 0xD3, 0xD6),
  156. SkPackARGB32(0xFF, 0x42, 0x41, 0x42)
  157. };
  158. SkBitmap bg;
  159. bg.allocN32Pixels(2, 2, true);
  160. memcpy(bg.getPixels(), kCheckData, sizeof(kCheckData));
  161. SkMatrix lm;
  162. lm.setScale(SkIntToScalar(kCheckSize), SkIntToScalar(kCheckSize));
  163. fBGShader = bg.makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat, &lm);
  164. SkPaint bmpPaint;
  165. const SkPoint kCenter = { SkIntToScalar(kSize) / 2, SkIntToScalar(kSize) / 2 };
  166. const SkColor kColors[] = {
  167. SK_ColorTRANSPARENT, 0x80800000, 0xF020F060, SK_ColorWHITE
  168. };
  169. bmpPaint.setShader(SkGradientShader::MakeRadial(kCenter, 3 * SkIntToScalar(kSize) / 4,
  170. kColors, nullptr, SK_ARRAY_COUNT(kColors),
  171. SkTileMode::kRepeat));
  172. SkBitmap bmp;
  173. bmp.allocN32Pixels(kSize, kSize);
  174. SkCanvas bmpCanvas(bmp);
  175. bmpCanvas.clear(SK_ColorTRANSPARENT);
  176. SkRect rect = { SkIntToScalar(kSize) / 8, SkIntToScalar(kSize) / 8,
  177. 7 * SkIntToScalar(kSize) / 8, 7 * SkIntToScalar(kSize) / 8};
  178. bmpCanvas.drawRect(rect, bmpPaint);
  179. fBmpShader = bmp.makeShader();
  180. }
  181. enum {
  182. kCheckSize = 8,
  183. kSize = 30,
  184. kTestsPerRow = 15,
  185. };
  186. sk_sp<SkShader> fBGShader;
  187. sk_sp<SkShader> fBmpShader;
  188. typedef GM INHERITED;
  189. };
  190. //////////////////////////////////////////////////////////////////////////////
  191. DEF_GM(return new Xfermodes3GM;)
  192. }