Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Typedefs | Functions | Variables
DegenerateQuadsSlide.cpp File Reference
#include "include/core/SkCanvas.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPathEffect.h"
#include "include/effects/SkDashPathEffect.h"
#include "include/pathops/SkPathOps.h"
#include "include/private/base/SkTPin.h"
#include "src/gpu/ganesh/geometry/GrQuad.h"
#include "src/gpu/ganesh/ops/QuadPerEdgeAA.h"
#include "tools/viewer/ClickHandlerSlide.h"

Go to the source code of this file.

Classes

class  DegenerateQuadSlide
 
class  DegenerateQuadSlide::Click
 

Typedefs

using VertexSpec = skgpu::ganesh::QuadPerEdgeAA::VertexSpec
 
using ColorType = skgpu::ganesh::QuadPerEdgeAA::ColorType
 
using Subset = skgpu::ganesh::QuadPerEdgeAA::Subset
 
using IndexBufferOption = skgpu::ganesh::QuadPerEdgeAA::IndexBufferOption
 

Functions

static void draw_extended_line (SkCanvas *canvas, const SkPaint &paint, const SkPoint &p0, const SkPoint &p1)
 
static void make_aa_line (const SkPoint &p0, const SkPoint &p1, bool aaOn, bool outset, SkPoint line[2])
 
static SkScalar signed_distance (const SkPoint &p, const SkPoint &l0, const SkPoint &l1)
 
static SkScalar get_area_coverage (const bool edgeAA[4], const SkPoint corners[4], const SkPoint &point)
 
static SkScalar get_edge_dist_coverage (const bool edgeAA[4], const SkPoint corners[4], const SkPoint outsetLines[8], const SkPoint insetLines[8], const SkPoint &point)
 
static bool inside_triangle (const SkPoint &point, const SkPoint &t0, const SkPoint &t1, const SkPoint &t2, SkScalar bary[3])
 
static SkScalar get_framed_coverage (const SkPoint outer[4], const SkScalar outerCoverages[4], const SkPoint inner[4], const SkScalar innerCoverages[4], const SkRect &geomDomain, const SkPoint &point)
 

Variables

static constexpr SkScalar kViewScale = 100.f
 
static constexpr SkScalar kViewOffset = 200.f
 

Typedef Documentation

◆ ColorType

Definition at line 19 of file DegenerateQuadsSlide.cpp.

◆ IndexBufferOption

Definition at line 21 of file DegenerateQuadsSlide.cpp.

◆ Subset

Definition at line 20 of file DegenerateQuadsSlide.cpp.

◆ VertexSpec

Definition at line 18 of file DegenerateQuadsSlide.cpp.

Function Documentation

◆ draw_extended_line()

static void draw_extended_line ( SkCanvas canvas,
const SkPaint paint,
const SkPoint p0,
const SkPoint p1 
)
static

Definition at line 24 of file DegenerateQuadsSlide.cpp.

25 {
26 SkVector v = p1 - p0;
27 v.setLength(v.length() + 3.f);
28 canvas->drawLine(p1 - v, p0 + v, paint);
29
30 // Draw normal vector too
31 SkPaint normalPaint = paint;
32 normalPaint.setPathEffect(nullptr);
33 normalPaint.setStrokeWidth(paint.getStrokeWidth() / 4.f);
34
35 SkVector n = {v.fY, -v.fX};
36 n.setLength(.25f);
37 SkPoint m = (p0 + p1) * 0.5f;
38 canvas->drawLine(m, m + n, normalPaint);
39}
void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint &paint)
void setPathEffect(sk_sp< SkPathEffect > pathEffect)
void setStrokeWidth(SkScalar width)
Definition SkPaint.cpp:159
const Paint & paint
bool setLength(float length)
Definition SkPoint.cpp:30
float fX
x-axis value
float length() const
float fY
y-axis value

◆ get_area_coverage()

static SkScalar get_area_coverage ( const bool  edgeAA[4],
const SkPoint  corners[4],
const SkPoint point 
)
static

Definition at line 63 of file DegenerateQuadsSlide.cpp.

64 {
65 SkPath shape;
66 shape.addPoly(corners, 4, true);
67 SkPath pixel;
68 pixel.addRect(SkRect::MakeXYWH(point.fX - 0.5f, point.fY - 0.5f, 1.f, 1.f));
69
70 SkPath intersection;
71 if (!Op(shape, pixel, kIntersect_SkPathOp, &intersection) || intersection.isEmpty()) {
72 return 0.f;
73 }
74
75 // Calculate area of the convex polygon
76 SkScalar area = 0.f;
77 for (int i = 0; i < intersection.countPoints(); ++i) {
78 SkPoint p0 = intersection.getPoint(i);
79 SkPoint p1 = intersection.getPoint((i + 1) % intersection.countPoints());
80 SkScalar det = p0.fX * p1.fY - p1.fX * p0.fY;
81 area += det;
82 }
83
84 // Scale by 1/2, then take abs value (this area formula is signed based on point winding, but
85 // since it's convex, just make it positive).
86 area = SkScalarAbs(0.5f * area);
87
88 // Now account for the edge AA. If the pixel center is outside of a non-AA edge, turn of its
89 // coverage. If the pixel only intersects non-AA edges, then set coverage to 1.
90 bool needsNonAA = false;
91 SkScalar edgeD[4];
92 for (int i = 0; i < 4; ++i) {
93 SkPoint e0 = corners[i];
94 SkPoint e1 = corners[(i + 1) % 4];
95 edgeD[i] = -signed_distance(point, e0, e1);
96 if (!edgeAA[i]) {
97 if (edgeD[i] < -1e-4f) {
98 return 0.f; // Outside of non-AA line
99 }
100 needsNonAA = true;
101 }
102 }
103 // Otherwise inside the shape, so check if any AA edge exerts influence over nonAA
104 if (needsNonAA) {
105 for (int i = 0; i < 4; i++) {
106 if (edgeAA[i] && edgeD[i] < 0.5f) {
107 needsNonAA = false;
108 break;
109 }
110 }
111 }
112 return needsNonAA ? 1.f : area;
113}
static SkScalar signed_distance(const SkPoint &p, const SkPoint &l0, const SkPoint &l1)
float e1
float e0
@ kIntersect_SkPathOp
intersect the two paths
Definition SkPathOps.h:24
#define SkScalarAbs(x)
Definition SkScalar.h:39
bool isEmpty() const
Definition SkPath.cpp:406
int countPoints() const
Definition SkPath.cpp:525
SkPoint getPoint(int index) const
Definition SkPath.cpp:539
SkPath & addPoly(const SkPoint pts[], int count, bool close)
Definition SkPath.cpp:880
SkPath & addRect(const SkRect &rect, SkPathDirection dir, unsigned start)
Definition SkPath.cpp:854
float SkScalar
Definition extension.cpp:12
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
Definition SkRect.h:659

◆ get_edge_dist_coverage()

static SkScalar get_edge_dist_coverage ( const bool  edgeAA[4],
const SkPoint  corners[4],
const SkPoint  outsetLines[8],
const SkPoint  insetLines[8],
const SkPoint point 
)
static

Definition at line 116 of file DegenerateQuadsSlide.cpp.

118 {
119 bool flip = false;
120 // If the quad has been inverted, the original corners will not all be on the negative side of
121 // every outset line. When that happens, calculate coverage using the "inset" lines and flip
122 // the signed distance
123 for (int i = 0; i < 4; ++i) {
124 for (int j = 0; j < 4; ++j) {
125 SkScalar d = signed_distance(corners[i], outsetLines[j * 2], outsetLines[j * 2 + 1]);
126 if (d > 1e-4f) {
127 flip = true;
128 break;
129 }
130 }
131 if (flip) {
132 break;
133 }
134 }
135
136 const SkPoint* lines = flip ? insetLines : outsetLines;
137
138 SkScalar minCoverage = 1.f;
139 for (int i = 0; i < 4; ++i) {
140 // Multiply by negative 1 so that outside points have negative distances
141 SkScalar d = (flip ? 1 : -1) * signed_distance(point, lines[i * 2], lines[i * 2 + 1]);
142 if (!edgeAA[i] && d >= -1e-4f) {
143 d = 1.f;
144 }
145 if (d < minCoverage) {
146 minCoverage = d;
147 if (minCoverage < 0.f) {
148 break; // Outside the shape
149 }
150 }
151 }
152 return minCoverage < 0.f ? 0.f : minCoverage;
153}
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition main.cc:19

◆ get_framed_coverage()

static SkScalar get_framed_coverage ( const SkPoint  outer[4],
const SkScalar  outerCoverages[4],
const SkPoint  inner[4],
const SkScalar  innerCoverages[4],
const SkRect geomDomain,
const SkPoint point 
)
static

Definition at line 193 of file DegenerateQuadsSlide.cpp.

195 {
196 // Triangles are ordered clock wise. Indices >= 4 refer to inner[i - 4]. Otherwise its outer[i].
197 static const int kFrameTris[] = {
198 0, 1, 4, 4, 1, 5,
199 1, 2, 5, 5, 2, 6,
200 2, 3, 6, 6, 3, 7,
201 3, 0, 7, 7, 0, 4,
202 4, 5, 7, 7, 5, 6
203 };
204 static const int kNumTris = 10;
205
206 SkScalar bary[3];
207 for (int i = 0; i < kNumTris; ++i) {
208 int i0 = kFrameTris[i * 3];
209 int i1 = kFrameTris[i * 3 + 1];
210 int i2 = kFrameTris[i * 3 + 2];
211
212 SkPoint t0 = i0 >= 4 ? inner[i0 - 4] : outer[i0];
213 SkPoint t1 = i1 >= 4 ? inner[i1 - 4] : outer[i1];
214 SkPoint t2 = i2 >= 4 ? inner[i2 - 4] : outer[i2];
215 if (inside_triangle(point, t0, t1, t2, bary)) {
216 // Calculate coverage by barycentric interpolation of coverages
217 SkScalar c0 = i0 >= 4 ? innerCoverages[i0 - 4] : outerCoverages[i0];
218 SkScalar c1 = i1 >= 4 ? innerCoverages[i1 - 4] : outerCoverages[i1];
219 SkScalar c2 = i2 >= 4 ? innerCoverages[i2 - 4] : outerCoverages[i2];
220
221 SkScalar coverage = bary[0] * c0 + bary[1] * c1 + bary[2] * c2;
222 if (coverage < 0.5f) {
223 // Check distances to domain
224 SkScalar l = SkTPin(point.fX - geomDomain.fLeft, 0.f, 1.f);
225 SkScalar t = SkTPin(point.fY - geomDomain.fTop, 0.f, 1.f);
226 SkScalar r = SkTPin(geomDomain.fRight - point.fX, 0.f, 1.f);
227 SkScalar b = SkTPin(geomDomain.fBottom - point.fY, 0.f, 1.f);
228 coverage = std::min(coverage, l * t * r * b);
229 }
230 return coverage;
231 }
232 }
233 // Not inside any triangle
234 return 0.f;
235}
static bool inside_triangle(const SkPoint &point, const SkPoint &t0, const SkPoint &t1, const SkPoint &t2, SkScalar bary[3])
static constexpr const T & SkTPin(const T &x, const T &lo, const T &hi)
Definition SkTPin.h:19
static bool b
SkScalar fBottom
larger y-axis bounds
Definition extension.cpp:17
SkScalar fLeft
smaller x-axis bounds
Definition extension.cpp:14
SkScalar fRight
larger x-axis bounds
Definition extension.cpp:16
SkScalar fTop
smaller y-axis bounds
Definition extension.cpp:15

◆ inside_triangle()

static bool inside_triangle ( const SkPoint point,
const SkPoint t0,
const SkPoint t1,
const SkPoint t2,
SkScalar  bary[3] 
)
static

Definition at line 155 of file DegenerateQuadsSlide.cpp.

156 {
157 // Check sign of t0 to (t1,t2). If it is positive, that means the normals point into the
158 // triangle otherwise the normals point outside the triangle so update edge distances as
159 // necessary
160 bool flip = signed_distance(t0, t1, t2) < 0.f;
161
162 SkScalar d0 = (flip ? -1 : 1) * signed_distance(point, t0, t1);
163 SkScalar d1 = (flip ? -1 : 1) * signed_distance(point, t1, t2);
164 SkScalar d2 = (flip ? -1 : 1) * signed_distance(point, t2, t0);
165 // Be a little forgiving
166 if (d0 < -1e-4f || d1 < -1e-4f || d2 < -1e-4f) {
167 return false;
168 }
169
170 // Inside, so calculate barycentric coords from the sideline distances
171 SkScalar d01 = (t0 - t1).length();
172 SkScalar d12 = (t1 - t2).length();
173 SkScalar d20 = (t2 - t0).length();
174
176 // Empty degenerate triangle
177 return false;
178 }
179
180 // Coordinates for a vertex use distances to the opposite edge
181 bary[0] = d1 * d12;
182 bary[1] = d2 * d20;
183 bary[2] = d0 * d01;
184 // And normalize
185 SkScalar sum = bary[0] + bary[1] + bary[2];
186 bary[0] /= sum;
187 bary[1] /= sum;
188 bary[2] /= sum;
189
190 return true;
191}
static bool SkScalarNearlyZero(SkScalar x, SkScalar tolerance=SK_ScalarNearlyZero)
Definition SkScalar.h:101
size_t length

◆ make_aa_line()

static void make_aa_line ( const SkPoint p0,
const SkPoint p1,
bool  aaOn,
bool  outset,
SkPoint  line[2] 
)
static

Definition at line 41 of file DegenerateQuadsSlide.cpp.

42 {
43 SkVector n = {0.f, 0.f};
44 if (aaOn) {
45 SkVector v = p1 - p0;
46 n = outset ? SkVector::Make(v.fY, -v.fX) : SkVector::Make(-v.fY, v.fX);
47 n.setLength(0.5f);
48 }
49
50 line[0] = p0 + n;
51 line[1] = p1 + n;
52}
static const int outset
Definition BlurTest.cpp:58
static std::unique_ptr< SkEncoder > Make(SkWStream *dst, const SkPixmap *src, const SkYUVAPixmaps *srcYUVA, const SkColorSpace *srcYUVAColorSpace, const SkJpegEncoder::Options &options)
static constexpr SkPoint Make(float x, float y)

◆ signed_distance()

static SkScalar signed_distance ( const SkPoint p,
const SkPoint l0,
const SkPoint l1 
)
static

Definition at line 55 of file DegenerateQuadsSlide.cpp.

55 {
56 SkVector v = l1 - l0;
57 v.normalize();
58 SkVector n = {v.fY, -v.fX};
59 SkScalar c = -n.dot(l0);
60 return n.dot(p) + c;
61}
float dot(const SkVector &vec) const
bool normalize()
Definition SkPoint.cpp:22

Variable Documentation

◆ kViewOffset

constexpr SkScalar kViewOffset = 200.f
staticconstexpr

Definition at line 238 of file DegenerateQuadsSlide.cpp.

◆ kViewScale

constexpr SkScalar kViewScale = 100.f
staticconstexpr

Definition at line 237 of file DegenerateQuadsSlide.cpp.