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