xref: /aosp_15_r20/external/skia/gm/polygons.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/SkCanvas.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColor.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPathBuilder.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTArray.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkRandom.h"
20*c8dee2aaSAndroid Build Coastguard Worker 
21*c8dee2aaSAndroid Build Coastguard Worker using namespace skia_private;
22*c8dee2aaSAndroid Build Coastguard Worker 
23*c8dee2aaSAndroid Build Coastguard Worker namespace skiagm {
24*c8dee2aaSAndroid Build Coastguard Worker 
25*c8dee2aaSAndroid Build Coastguard Worker // This GM tests a grab-bag of convex and concave polygons. They are triangles,
26*c8dee2aaSAndroid Build Coastguard Worker // trapezoid, diamond, polygons with lots of edges, several concave polygons...
27*c8dee2aaSAndroid Build Coastguard Worker // But rectangles are excluded.
28*c8dee2aaSAndroid Build Coastguard Worker class PolygonsGM: public GM {
29*c8dee2aaSAndroid Build Coastguard Worker public:
PolygonsGM()30*c8dee2aaSAndroid Build Coastguard Worker     PolygonsGM() {}
31*c8dee2aaSAndroid Build Coastguard Worker 
32*c8dee2aaSAndroid Build Coastguard Worker protected:
getName() const33*c8dee2aaSAndroid Build Coastguard Worker     SkString getName() const override { return SkString("polygons"); }
34*c8dee2aaSAndroid Build Coastguard Worker 
getISize()35*c8dee2aaSAndroid Build Coastguard Worker     SkISize getISize() override {
36*c8dee2aaSAndroid Build Coastguard Worker         int width = kNumPolygons * kCellSize + 40;
37*c8dee2aaSAndroid Build Coastguard Worker         int height = (kNumJoins * kNumStrokeWidths + kNumExtraStyles) * kCellSize + 40;
38*c8dee2aaSAndroid Build Coastguard Worker         return SkISize::Make(width, height);
39*c8dee2aaSAndroid Build Coastguard Worker     }
40*c8dee2aaSAndroid Build Coastguard Worker 
41*c8dee2aaSAndroid Build Coastguard Worker     // Construct all polygons
onOnceBeforeDraw()42*c8dee2aaSAndroid Build Coastguard Worker     void onOnceBeforeDraw() override {
43*c8dee2aaSAndroid Build Coastguard Worker         SkPoint p0[] = {{0, 0}, {60, 0}, {90, 40}};  // triangle
44*c8dee2aaSAndroid Build Coastguard Worker         SkPoint p1[] = {{0, 0}, {0, 40}, {60, 40}, {40, 0}};  // trapezoid
45*c8dee2aaSAndroid Build Coastguard Worker         SkPoint p2[] = {{0, 0}, {40, 40}, {80, 40}, {40, 0}};  // diamond
46*c8dee2aaSAndroid Build Coastguard Worker         SkPoint p3[] = {{10, 0}, {50, 0}, {60, 10}, {60, 30}, {50, 40},
47*c8dee2aaSAndroid Build Coastguard Worker                         {10, 40}, {0, 30}, {0, 10}};  // octagon
48*c8dee2aaSAndroid Build Coastguard Worker         SkPoint p4[32];  // circle-like polygons with 32-edges.
49*c8dee2aaSAndroid Build Coastguard Worker         SkPoint p5[] = {{0, 0}, {20, 20}, {0, 40}, {60, 20}};  // concave polygon with 4 edges
50*c8dee2aaSAndroid Build Coastguard Worker         SkPoint p6[] = {{0, 40}, {0, 30}, {15, 30}, {15, 20}, {30, 20},
51*c8dee2aaSAndroid Build Coastguard Worker                         {30, 10}, {45, 10}, {45, 0}, {60, 0}, {60, 40}};  // stairs-like polygon
52*c8dee2aaSAndroid Build Coastguard Worker         SkPoint p7[] = {{0, 20}, {20, 20}, {30, 0}, {40, 20}, {60, 20},
53*c8dee2aaSAndroid Build Coastguard Worker                         {45, 30}, {55, 50}, {30, 40}, {5, 50}, {15, 30}};  // five-point stars
54*c8dee2aaSAndroid Build Coastguard Worker 
55*c8dee2aaSAndroid Build Coastguard Worker         for (size_t i = 0; i < std::size(p4); ++i) {
56*c8dee2aaSAndroid Build Coastguard Worker             SkScalar angle = 2 * SK_ScalarPI * i / std::size(p4);
57*c8dee2aaSAndroid Build Coastguard Worker             p4[i].set(20 * SkScalarCos(angle) + 20, 20 * SkScalarSin(angle) + 20);
58*c8dee2aaSAndroid Build Coastguard Worker         }
59*c8dee2aaSAndroid Build Coastguard Worker 
60*c8dee2aaSAndroid Build Coastguard Worker         struct Polygons {
61*c8dee2aaSAndroid Build Coastguard Worker             SkPoint* fPoints;
62*c8dee2aaSAndroid Build Coastguard Worker             size_t fPointNum;
63*c8dee2aaSAndroid Build Coastguard Worker         } pgs[] = {
64*c8dee2aaSAndroid Build Coastguard Worker             { p0, std::size(p0) },
65*c8dee2aaSAndroid Build Coastguard Worker             { p1, std::size(p1) },
66*c8dee2aaSAndroid Build Coastguard Worker             { p2, std::size(p2) },
67*c8dee2aaSAndroid Build Coastguard Worker             { p3, std::size(p3) },
68*c8dee2aaSAndroid Build Coastguard Worker             { p4, std::size(p4) },
69*c8dee2aaSAndroid Build Coastguard Worker             { p5, std::size(p5) },
70*c8dee2aaSAndroid Build Coastguard Worker             { p6, std::size(p6) },
71*c8dee2aaSAndroid Build Coastguard Worker             { p7, std::size(p7) }
72*c8dee2aaSAndroid Build Coastguard Worker         };
73*c8dee2aaSAndroid Build Coastguard Worker 
74*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(std::size(pgs) == kNumPolygons);
75*c8dee2aaSAndroid Build Coastguard Worker         for (size_t pgIndex = 0; pgIndex < std::size(pgs); ++pgIndex) {
76*c8dee2aaSAndroid Build Coastguard Worker             SkPathBuilder b;
77*c8dee2aaSAndroid Build Coastguard Worker             b.moveTo(pgs[pgIndex].fPoints[0].fX,
78*c8dee2aaSAndroid Build Coastguard Worker                      pgs[pgIndex].fPoints[0].fY);
79*c8dee2aaSAndroid Build Coastguard Worker             for (size_t ptIndex = 1; ptIndex < pgs[pgIndex].fPointNum; ++ptIndex) {
80*c8dee2aaSAndroid Build Coastguard Worker                 b.lineTo(pgs[pgIndex].fPoints[ptIndex].fX,
81*c8dee2aaSAndroid Build Coastguard Worker                          pgs[pgIndex].fPoints[ptIndex].fY);
82*c8dee2aaSAndroid Build Coastguard Worker             }
83*c8dee2aaSAndroid Build Coastguard Worker             b.close();
84*c8dee2aaSAndroid Build Coastguard Worker             fPolygons.push_back(b.detach());
85*c8dee2aaSAndroid Build Coastguard Worker         }
86*c8dee2aaSAndroid Build Coastguard Worker     }
87*c8dee2aaSAndroid Build Coastguard Worker 
88*c8dee2aaSAndroid Build Coastguard Worker     // Set the location for the current test on the canvas
SetLocation(SkCanvas * canvas,int counter,int lineNum)89*c8dee2aaSAndroid Build Coastguard Worker     static void SetLocation(SkCanvas* canvas, int counter, int lineNum) {
90*c8dee2aaSAndroid Build Coastguard Worker         SkScalar x = SK_Scalar1 * kCellSize * (counter % lineNum) + 30 + SK_Scalar1 / 4;
91*c8dee2aaSAndroid Build Coastguard Worker         SkScalar y = SK_Scalar1 * kCellSize * (counter / lineNum) + 30 + 3 * SK_Scalar1 / 4;
92*c8dee2aaSAndroid Build Coastguard Worker         canvas->translate(x, y);
93*c8dee2aaSAndroid Build Coastguard Worker     }
94*c8dee2aaSAndroid Build Coastguard Worker 
SetColorAndAlpha(SkPaint * paint,SkRandom * rand)95*c8dee2aaSAndroid Build Coastguard Worker     static void SetColorAndAlpha(SkPaint* paint, SkRandom* rand) {
96*c8dee2aaSAndroid Build Coastguard Worker         SkColor color = rand->nextU();
97*c8dee2aaSAndroid Build Coastguard Worker         color |= 0xff000000;
98*c8dee2aaSAndroid Build Coastguard Worker         paint->setColor(color);
99*c8dee2aaSAndroid Build Coastguard Worker         if (40 == paint->getStrokeWidth()) {
100*c8dee2aaSAndroid Build Coastguard Worker             paint->setAlpha(0xA0);
101*c8dee2aaSAndroid Build Coastguard Worker         }
102*c8dee2aaSAndroid Build Coastguard Worker     }
103*c8dee2aaSAndroid Build Coastguard Worker 
onDraw(SkCanvas * canvas)104*c8dee2aaSAndroid Build Coastguard Worker     void onDraw(SkCanvas* canvas) override {
105*c8dee2aaSAndroid Build Coastguard Worker         // Stroke widths are:
106*c8dee2aaSAndroid Build Coastguard Worker         // 0(may use hairline rendering), 10(common case for stroke-style)
107*c8dee2aaSAndroid Build Coastguard Worker         // 40(>= geometry width/height, make the contour filled in fact)
108*c8dee2aaSAndroid Build Coastguard Worker         constexpr int kStrokeWidths[] = {0, 10, 40};
109*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(kNumStrokeWidths == std::size(kStrokeWidths));
110*c8dee2aaSAndroid Build Coastguard Worker 
111*c8dee2aaSAndroid Build Coastguard Worker         constexpr SkPaint::Join kJoins[] = {
112*c8dee2aaSAndroid Build Coastguard Worker             SkPaint::kMiter_Join, SkPaint::kRound_Join, SkPaint::kBevel_Join
113*c8dee2aaSAndroid Build Coastguard Worker         };
114*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(kNumJoins == std::size(kJoins));
115*c8dee2aaSAndroid Build Coastguard Worker 
116*c8dee2aaSAndroid Build Coastguard Worker         int counter = 0;
117*c8dee2aaSAndroid Build Coastguard Worker         SkPaint paint;
118*c8dee2aaSAndroid Build Coastguard Worker         paint.setAntiAlias(true);
119*c8dee2aaSAndroid Build Coastguard Worker 
120*c8dee2aaSAndroid Build Coastguard Worker         SkRandom rand;
121*c8dee2aaSAndroid Build Coastguard Worker         // For stroke style painter
122*c8dee2aaSAndroid Build Coastguard Worker         paint.setStyle(SkPaint::kStroke_Style);
123*c8dee2aaSAndroid Build Coastguard Worker         for (int join = 0; join < kNumJoins; ++join) {
124*c8dee2aaSAndroid Build Coastguard Worker             for (int width = 0; width < kNumStrokeWidths; ++width) {
125*c8dee2aaSAndroid Build Coastguard Worker                 for (int i = 0; i < fPolygons.size(); ++i) {
126*c8dee2aaSAndroid Build Coastguard Worker                     canvas->save();
127*c8dee2aaSAndroid Build Coastguard Worker                     SetLocation(canvas, counter, fPolygons.size());
128*c8dee2aaSAndroid Build Coastguard Worker 
129*c8dee2aaSAndroid Build Coastguard Worker                     SetColorAndAlpha(&paint, &rand);
130*c8dee2aaSAndroid Build Coastguard Worker                     paint.setStrokeJoin(kJoins[join]);
131*c8dee2aaSAndroid Build Coastguard Worker                     paint.setStrokeWidth(SkIntToScalar(kStrokeWidths[width]));
132*c8dee2aaSAndroid Build Coastguard Worker 
133*c8dee2aaSAndroid Build Coastguard Worker                     canvas->drawPath(fPolygons[i], paint);
134*c8dee2aaSAndroid Build Coastguard Worker                     canvas->restore();
135*c8dee2aaSAndroid Build Coastguard Worker                     ++counter;
136*c8dee2aaSAndroid Build Coastguard Worker                 }
137*c8dee2aaSAndroid Build Coastguard Worker             }
138*c8dee2aaSAndroid Build Coastguard Worker         }
139*c8dee2aaSAndroid Build Coastguard Worker 
140*c8dee2aaSAndroid Build Coastguard Worker         // For stroke-and-fill style painter and fill style painter
141*c8dee2aaSAndroid Build Coastguard Worker         constexpr SkPaint::Style kStyles[] = {
142*c8dee2aaSAndroid Build Coastguard Worker             SkPaint::kStrokeAndFill_Style, SkPaint::kFill_Style
143*c8dee2aaSAndroid Build Coastguard Worker         };
144*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(kNumExtraStyles == std::size(kStyles));
145*c8dee2aaSAndroid Build Coastguard Worker 
146*c8dee2aaSAndroid Build Coastguard Worker         paint.setStrokeJoin(SkPaint::kMiter_Join);
147*c8dee2aaSAndroid Build Coastguard Worker         paint.setStrokeWidth(SkIntToScalar(20));
148*c8dee2aaSAndroid Build Coastguard Worker         for (int style = 0; style < kNumExtraStyles; ++style) {
149*c8dee2aaSAndroid Build Coastguard Worker             paint.setStyle(kStyles[style]);
150*c8dee2aaSAndroid Build Coastguard Worker             for (int i = 0; i < fPolygons.size(); ++i) {
151*c8dee2aaSAndroid Build Coastguard Worker                 canvas->save();
152*c8dee2aaSAndroid Build Coastguard Worker                 SetLocation(canvas, counter, fPolygons.size());
153*c8dee2aaSAndroid Build Coastguard Worker                 SetColorAndAlpha(&paint, &rand);
154*c8dee2aaSAndroid Build Coastguard Worker                 canvas->drawPath(fPolygons[i], paint);
155*c8dee2aaSAndroid Build Coastguard Worker                 canvas->restore();
156*c8dee2aaSAndroid Build Coastguard Worker                 ++counter;
157*c8dee2aaSAndroid Build Coastguard Worker             }
158*c8dee2aaSAndroid Build Coastguard Worker         }
159*c8dee2aaSAndroid Build Coastguard Worker     }
160*c8dee2aaSAndroid Build Coastguard Worker 
161*c8dee2aaSAndroid Build Coastguard Worker private:
162*c8dee2aaSAndroid Build Coastguard Worker     inline static constexpr int kNumPolygons = 8;
163*c8dee2aaSAndroid Build Coastguard Worker     inline static constexpr int kCellSize = 100;
164*c8dee2aaSAndroid Build Coastguard Worker     inline static constexpr int kNumExtraStyles = 2;
165*c8dee2aaSAndroid Build Coastguard Worker     inline static constexpr int kNumStrokeWidths = 3;
166*c8dee2aaSAndroid Build Coastguard Worker     inline static constexpr int kNumJoins = 3;
167*c8dee2aaSAndroid Build Coastguard Worker 
168*c8dee2aaSAndroid Build Coastguard Worker     TArray<SkPath> fPolygons;
169*c8dee2aaSAndroid Build Coastguard Worker     using INHERITED = GM;
170*c8dee2aaSAndroid Build Coastguard Worker };
171*c8dee2aaSAndroid Build Coastguard Worker 
172*c8dee2aaSAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////////////
173*c8dee2aaSAndroid Build Coastguard Worker 
174*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new PolygonsGM;)
175*c8dee2aaSAndroid Build Coastguard Worker 
176*c8dee2aaSAndroid Build Coastguard Worker // see crbug.com/1197461
177*c8dee2aaSAndroid Build Coastguard Worker DEF_SIMPLE_GM(conjoined_polygons, canvas, 400, 400) {
178*c8dee2aaSAndroid Build Coastguard Worker     SkPathBuilder b;
179*c8dee2aaSAndroid Build Coastguard Worker     b.moveTo(0.f, 120.f);
180*c8dee2aaSAndroid Build Coastguard Worker     b.lineTo(0.f, 0.f);
181*c8dee2aaSAndroid Build Coastguard Worker     b.lineTo(50.f, 330.f);
182*c8dee2aaSAndroid Build Coastguard Worker     b.lineTo(90.f, 0.f);
183*c8dee2aaSAndroid Build Coastguard Worker     b.lineTo(340.f, 0.f);
184*c8dee2aaSAndroid Build Coastguard Worker     b.lineTo(90.f, 330.f);
185*c8dee2aaSAndroid Build Coastguard Worker     b.lineTo(50.f, 330.f);
186*c8dee2aaSAndroid Build Coastguard Worker     b.close();
187*c8dee2aaSAndroid Build Coastguard Worker 
188*c8dee2aaSAndroid Build Coastguard Worker     SkPaint paint;
189*c8dee2aaSAndroid Build Coastguard Worker     paint.setAntiAlias(true);
190*c8dee2aaSAndroid Build Coastguard Worker     canvas->drawPath(b.detach(), paint);
191*c8dee2aaSAndroid Build Coastguard Worker }
192*c8dee2aaSAndroid Build Coastguard Worker 
193*c8dee2aaSAndroid Build Coastguard Worker }  // namespace skiagm
194