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