dstreadshuffle.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  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/SkBlendMode.h"
  9. #include "include/core/SkCanvas.h"
  10. #include "include/core/SkColor.h"
  11. #include "include/core/SkColorSpace.h"
  12. #include "include/core/SkFont.h"
  13. #include "include/core/SkImageInfo.h"
  14. #include "include/core/SkMatrix.h"
  15. #include "include/core/SkPaint.h"
  16. #include "include/core/SkPath.h"
  17. #include "include/core/SkPoint.h"
  18. #include "include/core/SkRect.h"
  19. #include "include/core/SkRefCnt.h"
  20. #include "include/core/SkScalar.h"
  21. #include "include/core/SkSize.h"
  22. #include "include/core/SkString.h"
  23. #include "include/core/SkSurface.h"
  24. #include "include/core/SkTypeface.h"
  25. #include "include/core/SkTypes.h"
  26. #include "include/utils/SkRandom.h"
  27. #include "tools/ToolUtils.h"
  28. namespace skiagm {
  29. /**
  30. * Renders overlapping shapes with colorburn against a checkerboard.
  31. */
  32. class DstReadShuffle : public GM {
  33. public:
  34. DstReadShuffle() { this->setBGColor(kBackground); }
  35. protected:
  36. enum ShapeType {
  37. kCircle_ShapeType,
  38. kRoundRect_ShapeType,
  39. kRect_ShapeType,
  40. kConvexPath_ShapeType,
  41. kConcavePath_ShapeType,
  42. kText_ShapeType,
  43. kNumShapeTypes
  44. };
  45. SkString onShortName() override {
  46. return SkString("dstreadshuffle");
  47. }
  48. SkISize onISize() override {
  49. return SkISize::Make(530, 680);
  50. }
  51. void drawShape(SkCanvas* canvas, SkPaint* paint, ShapeType type) {
  52. const SkRect kRect = SkRect::MakeXYWH(0, 0, 75.f, 85.f);
  53. switch (type) {
  54. case kCircle_ShapeType:
  55. canvas->drawCircle(kRect.centerX(), kRect.centerY(), kRect.width() / 2.f, *paint);
  56. break;
  57. case kRoundRect_ShapeType:
  58. canvas->drawRoundRect(kRect, 15.f, 15.f, *paint);
  59. break;
  60. case kRect_ShapeType:
  61. canvas->drawRect(kRect, *paint);
  62. break;
  63. case kConvexPath_ShapeType:
  64. if (fConvexPath.isEmpty()) {
  65. SkPoint points[4];
  66. kRect.toQuad(points);
  67. fConvexPath.moveTo(points[0]);
  68. fConvexPath.quadTo(points[1], points[2]);
  69. fConvexPath.quadTo(points[3], points[0]);
  70. SkASSERT(fConvexPath.isConvex());
  71. }
  72. canvas->drawPath(fConvexPath, *paint);
  73. break;
  74. case kConcavePath_ShapeType:
  75. if (fConcavePath.isEmpty()) {
  76. SkPoint points[5] = {{50.f, 0.f}};
  77. SkMatrix rot;
  78. rot.setRotate(360.f / 5, 50.f, 70.f);
  79. for (int i = 1; i < 5; ++i) {
  80. rot.mapPoints(points + i, points + i - 1, 1);
  81. }
  82. fConcavePath.moveTo(points[0]);
  83. for (int i = 0; i < 5; ++i) {
  84. fConcavePath.lineTo(points[(2 * i) % 5]);
  85. }
  86. fConcavePath.setFillType(SkPath::kEvenOdd_FillType);
  87. SkASSERT(!fConcavePath.isConvex());
  88. }
  89. canvas->drawPath(fConcavePath, *paint);
  90. break;
  91. case kText_ShapeType: {
  92. const char* text = "N";
  93. SkFont font(ToolUtils::create_portable_typeface(), 100);
  94. font.setEmbolden(true);
  95. canvas->drawString(text, 0.f, 100.f, font, *paint);
  96. }
  97. default:
  98. break;
  99. }
  100. }
  101. static SkColor GetColor(SkRandom* random) {
  102. SkColor color = ToolUtils::color_to_565(random->nextU() | 0xFF000000);
  103. return SkColorSetA(color, 0x80);
  104. }
  105. static void DrawHairlines(SkCanvas* canvas) {
  106. if (canvas->imageInfo().alphaType() == kOpaque_SkAlphaType) {
  107. canvas->clear(kBackground);
  108. } else {
  109. canvas->clear(SK_ColorTRANSPARENT);
  110. }
  111. SkPaint hairPaint;
  112. hairPaint.setStyle(SkPaint::kStroke_Style);
  113. hairPaint.setStrokeWidth(0);
  114. hairPaint.setAntiAlias(true);
  115. static constexpr int kNumHairlines = 12;
  116. SkPoint pts[] = {{3.f, 7.f}, {29.f, 7.f}};
  117. SkRandom colorRandom;
  118. SkMatrix rot;
  119. rot.setRotate(360.f / kNumHairlines, 15.5f, 12.f);
  120. rot.postTranslate(3.f, 0);
  121. for (int i = 0; i < 12; ++i) {
  122. hairPaint.setColor(GetColor(&colorRandom));
  123. canvas->drawLine(pts[0], pts[1], hairPaint);
  124. rot.mapPoints(pts, 2);
  125. }
  126. }
  127. void onDraw(SkCanvas* canvas) override {
  128. SkScalar y = 5;
  129. for (int i = 0; i < kNumShapeTypes; i++) {
  130. SkRandom colorRandom;
  131. ShapeType shapeType = static_cast<ShapeType>(i);
  132. SkScalar x = 5;
  133. for (int r = 0; r <= 15; r++) {
  134. SkPaint p;
  135. p.setAntiAlias(true);
  136. p.setColor(GetColor(&colorRandom));
  137. // In order to get some op combining on the GPU backend we do 2 src over
  138. // for each xfer mode which requires a dst read
  139. p.setBlendMode(r % 3 == 0 ? SkBlendMode::kColorBurn : SkBlendMode::kSrcOver);
  140. canvas->save();
  141. canvas->translate(x, y);
  142. this->drawShape(canvas, &p, shapeType);
  143. canvas->restore();
  144. x += 15;
  145. }
  146. y += 110;
  147. }
  148. // Draw hairlines to a surface and then draw that to the main canvas with a zoom so that
  149. // it is easier to see how they blend.
  150. SkImageInfo info;
  151. // Recording canvases don't have a color type.
  152. if (SkColorType::kUnknown_SkColorType == canvas->imageInfo().colorType()) {
  153. info = SkImageInfo::MakeN32Premul(35, 35);
  154. } else {
  155. info = SkImageInfo::Make(35, 35,
  156. canvas->imageInfo().colorType(),
  157. canvas->imageInfo().alphaType(),
  158. canvas->imageInfo().refColorSpace());
  159. }
  160. auto surf = canvas->makeSurface(info);
  161. if (!surf) {
  162. // Fall back to raster. Raster supports only one of the 8 bit per-channel RGBA or BGRA
  163. // formats. This fall back happens when running with --preAbandonGpuContext.
  164. if ((info.colorType() == kRGBA_8888_SkColorType ||
  165. info.colorType() == kBGRA_8888_SkColorType) &&
  166. info.colorType() != kN32_SkColorType) {
  167. info = SkImageInfo::Make(35, 35,
  168. kN32_SkColorType,
  169. canvas->imageInfo().alphaType(),
  170. canvas->imageInfo().refColorSpace());
  171. }
  172. surf = SkSurface::MakeRaster(info);
  173. SkASSERT(surf);
  174. }
  175. canvas->scale(5.f, 5.f);
  176. canvas->translate(67.f, 10.f);
  177. DrawHairlines(surf->getCanvas());
  178. canvas->drawImage(surf->makeImageSnapshot(), 0.f, 0.f);
  179. }
  180. private:
  181. static constexpr SkColor kBackground = SK_ColorLTGRAY;
  182. SkPath fConcavePath;
  183. SkPath fConvexPath;
  184. typedef GM INHERITED;
  185. };
  186. //////////////////////////////////////////////////////////////////////////////
  187. DEF_GM( return new DstReadShuffle; )
  188. }