xref: /aosp_15_r20/external/skia/gm/sharedcorners.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2018 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/SkMatrix.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPath.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkRandom.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "tools/ToolUtils.h"
22*c8dee2aaSAndroid Build Coastguard Worker 
23*c8dee2aaSAndroid Build Coastguard Worker #include <array>
24*c8dee2aaSAndroid Build Coastguard Worker #include <vector>
25*c8dee2aaSAndroid Build Coastguard Worker 
26*c8dee2aaSAndroid Build Coastguard Worker namespace skiagm {
27*c8dee2aaSAndroid Build Coastguard Worker 
28*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kPadSize = 20;
29*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kBoxSize = 100;
30*c8dee2aaSAndroid Build Coastguard Worker static constexpr SkPoint kJitters[] = {{0, 0}, {.5f, .5f}, {2/3.f, 1/3.f}};
31*c8dee2aaSAndroid Build Coastguard Worker 
32*c8dee2aaSAndroid Build Coastguard Worker // Tests various corners of different angles falling on the same pixel, particularly to ensure
33*c8dee2aaSAndroid Build Coastguard Worker // analytic AA is working properly.
34*c8dee2aaSAndroid Build Coastguard Worker class SharedCornersGM : public GM {
35*c8dee2aaSAndroid Build Coastguard Worker public:
SharedCornersGM()36*c8dee2aaSAndroid Build Coastguard Worker     SharedCornersGM() { this->setBGColor(ToolUtils::color_to_565(0xFF1A65D7)); }
37*c8dee2aaSAndroid Build Coastguard Worker 
38*c8dee2aaSAndroid Build Coastguard Worker protected:
getName() const39*c8dee2aaSAndroid Build Coastguard Worker     SkString getName() const override { return SkString("sharedcorners"); }
40*c8dee2aaSAndroid Build Coastguard Worker 
getISize()41*c8dee2aaSAndroid Build Coastguard Worker     SkISize getISize() override {
42*c8dee2aaSAndroid Build Coastguard Worker         constexpr int numRows = 3 * 2;
43*c8dee2aaSAndroid Build Coastguard Worker         constexpr int numCols = (1 + std::size(kJitters)) * 2;
44*c8dee2aaSAndroid Build Coastguard Worker         return SkISize::Make(numCols * (kBoxSize + kPadSize) + kPadSize,
45*c8dee2aaSAndroid Build Coastguard Worker                              numRows * (kBoxSize + kPadSize) + kPadSize);
46*c8dee2aaSAndroid Build Coastguard Worker     }
47*c8dee2aaSAndroid Build Coastguard Worker 
onOnceBeforeDraw()48*c8dee2aaSAndroid Build Coastguard Worker     void onOnceBeforeDraw() override {
49*c8dee2aaSAndroid Build Coastguard Worker         fFillPaint.setColor(SK_ColorWHITE);
50*c8dee2aaSAndroid Build Coastguard Worker         fFillPaint.setAntiAlias(true);
51*c8dee2aaSAndroid Build Coastguard Worker 
52*c8dee2aaSAndroid Build Coastguard Worker         fWireFramePaint = fFillPaint;
53*c8dee2aaSAndroid Build Coastguard Worker         fWireFramePaint.setStyle(SkPaint::kStroke_Style);
54*c8dee2aaSAndroid Build Coastguard Worker 
55*c8dee2aaSAndroid Build Coastguard Worker     }
56*c8dee2aaSAndroid Build Coastguard Worker 
onDraw(SkCanvas * canvas)57*c8dee2aaSAndroid Build Coastguard Worker     void onDraw(SkCanvas* canvas) override {
58*c8dee2aaSAndroid Build Coastguard Worker         canvas->translate(kPadSize, kPadSize);
59*c8dee2aaSAndroid Build Coastguard Worker         canvas->save();
60*c8dee2aaSAndroid Build Coastguard Worker 
61*c8dee2aaSAndroid Build Coastguard Worker         // Adjacent rects.
62*c8dee2aaSAndroid Build Coastguard Worker         this->drawTriangleBoxes(canvas,
63*c8dee2aaSAndroid Build Coastguard Worker                 {{0,  0}, {40,  0}, {80,  0}, {120,  0},
64*c8dee2aaSAndroid Build Coastguard Worker                  {0, 20}, {40, 20}, {80, 20}, {120, 20},
65*c8dee2aaSAndroid Build Coastguard Worker                           {40, 40}, {80, 40},
66*c8dee2aaSAndroid Build Coastguard Worker                           {40, 60}, {80, 60}},
67*c8dee2aaSAndroid Build Coastguard Worker                 {{{0, 1, 4}}, {{1, 5, 4}},
68*c8dee2aaSAndroid Build Coastguard Worker                  {{5, 1, 6}}, {{1, 2, 6}},
69*c8dee2aaSAndroid Build Coastguard Worker                  {{2, 3, 6}}, {{3, 7, 6}},
70*c8dee2aaSAndroid Build Coastguard Worker                  {{8, 5, 9}}, {{5, 6, 9}},
71*c8dee2aaSAndroid Build Coastguard Worker                  {{10, 8, 11}}, {{8, 9, 11}}});
72*c8dee2aaSAndroid Build Coastguard Worker 
73*c8dee2aaSAndroid Build Coastguard Worker         // Obtuse angles.
74*c8dee2aaSAndroid Build Coastguard Worker         this->drawTriangleBoxes(canvas,
75*c8dee2aaSAndroid Build Coastguard Worker                 {{ 0, 0}, {10, 0}, {20, 0},
76*c8dee2aaSAndroid Build Coastguard Worker                  { 0, 2},          {20, 2},
77*c8dee2aaSAndroid Build Coastguard Worker                           {10, 4},
78*c8dee2aaSAndroid Build Coastguard Worker                  { 0, 6},          {20, 6},
79*c8dee2aaSAndroid Build Coastguard Worker                  { 0, 8}, {10, 8}, {20, 8}},
80*c8dee2aaSAndroid Build Coastguard Worker                 {{{3, 1, 4}}, {{4, 5, 3}}, {{6, 5, 7}}, {{7, 9, 6}},
81*c8dee2aaSAndroid Build Coastguard Worker                  {{0, 1, 3}}, {{1, 2, 4}},
82*c8dee2aaSAndroid Build Coastguard Worker                  {{3, 5, 6}}, {{5, 4, 7}},
83*c8dee2aaSAndroid Build Coastguard Worker                  {{6, 9, 8}}, {{9, 7, 10}}});
84*c8dee2aaSAndroid Build Coastguard Worker 
85*c8dee2aaSAndroid Build Coastguard Worker         canvas->restore();
86*c8dee2aaSAndroid Build Coastguard Worker         canvas->translate((kBoxSize + kPadSize) * 4, 0);
87*c8dee2aaSAndroid Build Coastguard Worker 
88*c8dee2aaSAndroid Build Coastguard Worker         // Right angles.
89*c8dee2aaSAndroid Build Coastguard Worker         this->drawTriangleBoxes(canvas,
90*c8dee2aaSAndroid Build Coastguard Worker                 {{0, 0}, {-1, 0}, {0, -1}, {1, 0}, {0, 1}},
91*c8dee2aaSAndroid Build Coastguard Worker                 {{{0, 1, 2}}, {{0, 2, 3}}, {{0, 3, 4}}, {{0, 4, 1}}});
92*c8dee2aaSAndroid Build Coastguard Worker 
93*c8dee2aaSAndroid Build Coastguard Worker         // Acute angles.
94*c8dee2aaSAndroid Build Coastguard Worker         SkRandom rand;
95*c8dee2aaSAndroid Build Coastguard Worker         std::vector<SkPoint> pts;
96*c8dee2aaSAndroid Build Coastguard Worker         std::vector<std::array<int, 3>> indices;
97*c8dee2aaSAndroid Build Coastguard Worker         SkScalar theta = 0;
98*c8dee2aaSAndroid Build Coastguard Worker         pts.push_back({0, 0});
99*c8dee2aaSAndroid Build Coastguard Worker         while (theta < 2*SK_ScalarPI) {
100*c8dee2aaSAndroid Build Coastguard Worker             pts.push_back({SkScalarCos(theta), SkScalarSin(theta)});
101*c8dee2aaSAndroid Build Coastguard Worker             if (pts.size() > 2) {
102*c8dee2aaSAndroid Build Coastguard Worker                 indices.push_back({{0, (int)pts.size() - 2, (int)pts.size() - 1}});
103*c8dee2aaSAndroid Build Coastguard Worker             }
104*c8dee2aaSAndroid Build Coastguard Worker             theta += rand.nextRangeF(0, SK_ScalarPI/3);
105*c8dee2aaSAndroid Build Coastguard Worker         }
106*c8dee2aaSAndroid Build Coastguard Worker         indices.push_back({{0, (int)pts.size() - 1, 1}});
107*c8dee2aaSAndroid Build Coastguard Worker         this->drawTriangleBoxes(canvas, pts, indices);
108*c8dee2aaSAndroid Build Coastguard Worker     }
109*c8dee2aaSAndroid Build Coastguard Worker 
drawTriangleBoxes(SkCanvas * canvas,const std::vector<SkPoint> & points,const std::vector<std::array<int,3>> & triangles)110*c8dee2aaSAndroid Build Coastguard Worker     void drawTriangleBoxes(SkCanvas* canvas, const std::vector<SkPoint>& points,
111*c8dee2aaSAndroid Build Coastguard Worker                            const std::vector<std::array<int, 3>>& triangles) {
112*c8dee2aaSAndroid Build Coastguard Worker         SkPath path;
113*c8dee2aaSAndroid Build Coastguard Worker         path.setFillType(SkPathFillType::kEvenOdd);
114*c8dee2aaSAndroid Build Coastguard Worker         path.setIsVolatile(true);
115*c8dee2aaSAndroid Build Coastguard Worker         for (const std::array<int, 3>& triangle : triangles) {
116*c8dee2aaSAndroid Build Coastguard Worker             path.moveTo(points[triangle[0]]);
117*c8dee2aaSAndroid Build Coastguard Worker             path.lineTo(points[triangle[1]]);
118*c8dee2aaSAndroid Build Coastguard Worker             path.lineTo(points[triangle[2]]);
119*c8dee2aaSAndroid Build Coastguard Worker             path.close();
120*c8dee2aaSAndroid Build Coastguard Worker         }
121*c8dee2aaSAndroid Build Coastguard Worker         SkScalar scale = kBoxSize / std::max(path.getBounds().height(), path.getBounds().width());
122*c8dee2aaSAndroid Build Coastguard Worker         path.transform(SkMatrix::Scale(scale, scale));
123*c8dee2aaSAndroid Build Coastguard Worker 
124*c8dee2aaSAndroid Build Coastguard Worker         this->drawRow(canvas, path);
125*c8dee2aaSAndroid Build Coastguard Worker         canvas->translate(0, kBoxSize + kPadSize);
126*c8dee2aaSAndroid Build Coastguard Worker 
127*c8dee2aaSAndroid Build Coastguard Worker         SkMatrix rot;
128*c8dee2aaSAndroid Build Coastguard Worker         rot.setRotate(45, path.getBounds().centerX(), path.getBounds().centerY());
129*c8dee2aaSAndroid Build Coastguard Worker         path.transform(rot);
130*c8dee2aaSAndroid Build Coastguard Worker         this->drawRow(canvas, path);
131*c8dee2aaSAndroid Build Coastguard Worker         canvas->translate(0, kBoxSize + kPadSize);
132*c8dee2aaSAndroid Build Coastguard Worker 
133*c8dee2aaSAndroid Build Coastguard Worker         rot.setRotate(-45 - 69.38111f, path.getBounds().centerX(), path.getBounds().centerY());
134*c8dee2aaSAndroid Build Coastguard Worker         path.transform(rot);
135*c8dee2aaSAndroid Build Coastguard Worker         this->drawRow(canvas, path);
136*c8dee2aaSAndroid Build Coastguard Worker         canvas->translate(0, kBoxSize + kPadSize);
137*c8dee2aaSAndroid Build Coastguard Worker     }
138*c8dee2aaSAndroid Build Coastguard Worker 
drawRow(SkCanvas * canvas,const SkPath & path)139*c8dee2aaSAndroid Build Coastguard Worker     void drawRow(SkCanvas* canvas, const SkPath& path) {
140*c8dee2aaSAndroid Build Coastguard Worker         SkAutoCanvasRestore acr(canvas, true);
141*c8dee2aaSAndroid Build Coastguard Worker         const SkRect& bounds = path.getBounds();
142*c8dee2aaSAndroid Build Coastguard Worker         canvas->translate((kBoxSize - bounds.width()) / 2 - bounds.left(),
143*c8dee2aaSAndroid Build Coastguard Worker                           (kBoxSize - bounds.height()) / 2 - bounds.top());
144*c8dee2aaSAndroid Build Coastguard Worker 
145*c8dee2aaSAndroid Build Coastguard Worker         canvas->drawPath(path, fWireFramePaint);
146*c8dee2aaSAndroid Build Coastguard Worker         canvas->translate(kBoxSize + kPadSize, 0);
147*c8dee2aaSAndroid Build Coastguard Worker 
148*c8dee2aaSAndroid Build Coastguard Worker         for (SkPoint jitter : kJitters) {
149*c8dee2aaSAndroid Build Coastguard Worker             {
150*c8dee2aaSAndroid Build Coastguard Worker                 SkAutoCanvasRestore acr2(canvas, true);
151*c8dee2aaSAndroid Build Coastguard Worker                 canvas->translate(jitter.x(), jitter.y());
152*c8dee2aaSAndroid Build Coastguard Worker                 canvas->drawPath(path, fFillPaint);
153*c8dee2aaSAndroid Build Coastguard Worker             }
154*c8dee2aaSAndroid Build Coastguard Worker             canvas->translate(kBoxSize + kPadSize, 0);
155*c8dee2aaSAndroid Build Coastguard Worker         }
156*c8dee2aaSAndroid Build Coastguard Worker     }
157*c8dee2aaSAndroid Build Coastguard Worker 
158*c8dee2aaSAndroid Build Coastguard Worker     SkPaint fWireFramePaint;
159*c8dee2aaSAndroid Build Coastguard Worker     SkPaint fFillPaint;
160*c8dee2aaSAndroid Build Coastguard Worker };
161*c8dee2aaSAndroid Build Coastguard Worker 
162*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new SharedCornersGM;)
163*c8dee2aaSAndroid Build Coastguard Worker 
164*c8dee2aaSAndroid Build Coastguard Worker }  // namespace skiagm
165