Chris Dalton | 47114db | 2021-01-06 00:35:20 -0700 | [diff] [blame] | 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 "src/gpu/GrTriangulator.h" |
| 12 | |
| 13 | // Triangulates the given path in device space with a mesh of alpha ramps for antialiasing. |
Chris Dalton | d538479 | 2021-01-20 15:43:24 -0700 | [diff] [blame] | 14 | class GrAATriangulator : private GrTriangulator { |
Chris Dalton | 47114db | 2021-01-06 00:35:20 -0700 | [diff] [blame] | 15 | public: |
Chris Dalton | d538479 | 2021-01-20 15:43:24 -0700 | [diff] [blame] | 16 | static int PathToAATriangles(const SkPath& path, SkScalar tolerance, const SkRect& clipBounds, |
| 17 | GrEagerVertexAllocator* vertexAllocator) { |
Chris Dalton | 8a42b09 | 2021-01-21 22:09:26 -0700 | [diff] [blame^] | 18 | SkArenaAlloc alloc(kArenaDefaultChunkSize); |
| 19 | GrAATriangulator aaTriangulator(path, &alloc); |
Chris Dalton | 47114db | 2021-01-06 00:35:20 -0700 | [diff] [blame] | 20 | aaTriangulator.fRoundVerticesToQuarterPixel = true; |
| 21 | aaTriangulator.fEmitCoverage = true; |
Chris Dalton | 37d16f1 | 2021-01-20 18:32:48 -0700 | [diff] [blame] | 22 | bool isLinear; |
| 23 | Poly* polys = aaTriangulator.pathToPolys(tolerance, clipBounds, &isLinear); |
Chris Dalton | d538479 | 2021-01-20 15:43:24 -0700 | [diff] [blame] | 24 | return aaTriangulator.polysToAATriangles(polys, vertexAllocator); |
Chris Dalton | 47114db | 2021-01-06 00:35:20 -0700 | [diff] [blame] | 25 | } |
| 26 | |
| 27 | // Structs used by GrAATriangulator internals. |
| 28 | struct SSEdge; |
| 29 | struct EventList; |
| 30 | struct Event { |
| 31 | Event(SSEdge* edge, const SkPoint& point, uint8_t alpha) |
| 32 | : fEdge(edge), fPoint(point), fAlpha(alpha) {} |
| 33 | SSEdge* fEdge; |
| 34 | SkPoint fPoint; |
| 35 | uint8_t fAlpha; |
| 36 | void apply(VertexList* mesh, const Comparator&, EventList* events, GrAATriangulator*); |
| 37 | }; |
| 38 | struct EventComparator { |
| 39 | enum class Op { kLessThan, kGreaterThan }; |
| 40 | EventComparator(Op op) : fOp(op) {} |
| 41 | bool operator() (Event* const &e1, Event* const &e2) { |
| 42 | return fOp == Op::kLessThan ? e1->fAlpha < e2->fAlpha |
| 43 | : e1->fAlpha > e2->fAlpha; |
| 44 | } |
| 45 | Op fOp; |
| 46 | }; |
| 47 | |
| 48 | private: |
Chris Dalton | 8a42b09 | 2021-01-21 22:09:26 -0700 | [diff] [blame^] | 49 | GrAATriangulator(const SkPath& path, SkArenaAlloc* alloc) : GrTriangulator(path, alloc) {} |
Chris Dalton | 47114db | 2021-01-06 00:35:20 -0700 | [diff] [blame] | 50 | |
| 51 | // For screenspace antialiasing, the algorithm is modified as follows: |
| 52 | // |
| 53 | // Run steps 1-5 above to produce polygons. |
| 54 | // 5b) Apply fill rules to extract boundary contours from the polygons: |
| 55 | void extractBoundary(EdgeList* boundary, Edge* e); |
| 56 | void extractBoundaries(const VertexList& inMesh, VertexList* innerVertices, const Comparator&); |
| 57 | |
| 58 | // 5c) Simplify boundaries to remove "pointy" vertices that cause inversions: |
| 59 | void simplifyBoundary(EdgeList* boundary, const Comparator&); |
| 60 | |
| 61 | // 5d) Displace edges by half a pixel inward and outward along their normals. Intersect to find |
| 62 | // new vertices, and set zero alpha on the exterior and one alpha on the interior. Build a |
| 63 | // new antialiased mesh from those vertices: |
| 64 | void strokeBoundary(EdgeList* boundary, VertexList* innerMesh, const Comparator&); |
| 65 | |
| 66 | // Run steps 3-6 above on the new mesh, and produce antialiased triangles. |
| 67 | Poly* tessellate(const VertexList& mesh, const Comparator&) override; |
Chris Dalton | d538479 | 2021-01-20 15:43:24 -0700 | [diff] [blame] | 68 | int polysToAATriangles(Poly*, GrEagerVertexAllocator*); |
Chris Dalton | 47114db | 2021-01-06 00:35:20 -0700 | [diff] [blame] | 69 | |
| 70 | // Additional helpers and driver functions. |
| 71 | void makeEvent(SSEdge*, EventList* events); |
| 72 | void makeEvent(SSEdge*, Vertex* v, SSEdge* other, Vertex* dest, EventList* events, |
| 73 | const Comparator&); |
| 74 | void connectPartners(VertexList* mesh, const Comparator&); |
| 75 | void removeNonBoundaryEdges(const VertexList& mesh); |
| 76 | void connectSSEdge(Vertex* v, Vertex* dest, const Comparator&); |
| 77 | bool collapseOverlapRegions(VertexList* mesh, const Comparator&, EventComparator comp); |
| 78 | |
| 79 | VertexList fOuterMesh; |
| 80 | }; |
| 81 | |
| 82 | #endif |