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