xref: /aosp_15_r20/external/skia/src/gpu/ganesh/geometry/GrAATriangulator.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2020 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 #ifndef GrAATriangulator_DEFINED
9 #define GrAATriangulator_DEFINED
10 
11 #include "include/core/SkTypes.h"
12 #if !defined(SK_ENABLE_OPTIMIZE_SIZE)
13 
14 #include "include/core/SkPoint.h"
15 #include "include/core/SkScalar.h"
16 #include "src/base/SkArenaAlloc.h"
17 #include "src/gpu/ganesh/geometry/GrTriangulator.h"
18 
19 #include <cstdint>
20 #include <tuple>
21 
22 class GrEagerVertexAllocator;
23 class SkPath;
24 struct SkRect;
25 
26 // Triangulates the given path in device space with a mesh of alpha ramps for antialiasing.
27 class GrAATriangulator : private GrTriangulator {
28 public:
PathToAATriangles(const SkPath & path,SkScalar tolerance,const SkRect & clipBounds,GrEagerVertexAllocator * vertexAllocator)29     static int PathToAATriangles(const SkPath& path, SkScalar tolerance, const SkRect& clipBounds,
30                                  GrEagerVertexAllocator* vertexAllocator) {
31         SkArenaAlloc alloc(kArenaDefaultChunkSize);
32         GrAATriangulator aaTriangulator(path, &alloc);
33         aaTriangulator.fRoundVerticesToQuarterPixel = true;
34         aaTriangulator.fEmitCoverage = true;
35         bool isLinear;
36         auto [ polys, success ] = aaTriangulator.pathToPolys(tolerance, clipBounds, &isLinear);
37         if (!success) {
38             return 0;
39         }
40         return aaTriangulator.polysToAATriangles(polys, vertexAllocator);
41     }
42 
43     // Structs used by GrAATriangulator internals.
44     struct SSEdge;
45     struct EventList;
46     struct Event {
EventEvent47         Event(SSEdge* edge, const SkPoint& point, uint8_t alpha)
48                 : fEdge(edge), fPoint(point), fAlpha(alpha) {}
49         SSEdge* fEdge;
50         SkPoint fPoint;
51         uint8_t fAlpha;
52         void apply(VertexList* mesh, const Comparator&, EventList* events, GrAATriangulator*);
53     };
54     struct EventComparator {
55         enum class Op { kLessThan, kGreaterThan };
EventComparatorEventComparator56         EventComparator(Op op) : fOp(op) {}
operatorEventComparator57         bool operator() (Event* const &e1, Event* const &e2) {
58             return fOp == Op::kLessThan ? e1->fAlpha < e2->fAlpha
59                                         : e1->fAlpha > e2->fAlpha;
60         }
61         Op fOp;
62     };
63 
64 private:
GrAATriangulator(const SkPath & path,SkArenaAlloc * alloc)65     GrAATriangulator(const SkPath& path, SkArenaAlloc* alloc) : GrTriangulator(path, alloc) {}
66 
67     // For screenspace antialiasing, the algorithm is modified as follows:
68     //
69     // Run steps 1-5 above to produce polygons.
70     // 5b) Apply fill rules to extract boundary contours from the polygons:
71     void extractBoundary(EdgeList* boundary, Edge* e) const;
72     void extractBoundaries(const VertexList& inMesh, VertexList* innerVertices,
73                            const Comparator&);
74 
75     // 5c) Simplify boundaries to remove "pointy" vertices that cause inversions:
76     void simplifyBoundary(EdgeList* boundary, const Comparator&);
77 
78     // 5d) Displace edges by half a pixel inward and outward along their normals. Intersect to find
79     //     new vertices, and set zero alpha on the exterior and one alpha on the interior. Build a
80     //     new antialiased mesh from those vertices:
81     void strokeBoundary(EdgeList* boundary, VertexList* innerMesh, const Comparator&);
82 
83     // Run steps 3-6 above on the new mesh, and produce antialiased triangles.
84     std::tuple<Poly*, bool> tessellate(const VertexList& mesh, const Comparator&) override;
85     int polysToAATriangles(Poly*, GrEagerVertexAllocator*) const;
86 
87     // Additional helpers and driver functions.
88     void makeEvent(SSEdge*, EventList* events) const;
89     void makeEvent(SSEdge*, Vertex* v, SSEdge* other, Vertex* dest, EventList* events,
90                    const Comparator&) const;
91     void connectPartners(VertexList* mesh, const Comparator&);
92     void removeNonBoundaryEdges(const VertexList& mesh) const;
93     void connectSSEdge(Vertex* v, Vertex* dest, const Comparator&);
94     bool collapseOverlapRegions(VertexList* mesh, const Comparator&, EventComparator comp);
95 
96     // FIXME: fOuterMesh should be plumbed through function parameters instead.
97     mutable VertexList fOuterMesh;
98 };
99 
100 #endif // SK_ENABLE_OPTIMIZE_SIZE
101 
102 #endif // GrAATriangulator_DEFINED
103