| /* | |
| * Copyright 2021 Google LLC | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #ifndef GrInnerFanTriangulator_DEFINED | |
| #define GrInnerFanTriangulator_DEFINED | |
| #if !defined(SK_ENABLE_OPTIMIZE_SIZE) | |
| #include "gr_triangulator.hpp" | |
| #include <optional> | |
| namespace rive | |
| { | |
| // Triangulates the inner polygon(s) of a path (i.e., the triangle fan for a | |
| // Redbook rendering method). When combined with the outer curves and grout | |
| // triangles, these produce a complete path. If a groutCollector is not | |
| // provided, pathToPolys fails upon self intersection. | |
| class GrInnerFanTriangulator : private GrTriangulator | |
| { | |
| public: | |
| using GroutTriangleList = GrTriangulator::BreadcrumbTriangleList; | |
| GrInnerFanTriangulator( | |
| const RawPath& path, | |
| const AABB& pathBounds, | |
| TrivialBlockAllocator* alloc) | |
| : GrTriangulator( | |
| // Sweep along the longer dimension of pathBounds so the sweep line | |
| // crosses fewer edges. | |
| pathBounds.width() > pathBounds.height() | |
| ? Comparator::Direction::kHorizontal | |
| : Comparator::Direction::kVertical, | |
| alloc) | |
| { | |
| fPreserveCollinearVertices = true; | |
| fCollectBreadcrumbTriangles = true; | |
| bool isLinear; | |
| auto [polys, success] = GrTriangulator::pathToPolys( | |
| path, | |
| 0, | |
| AABB{}, | |
| &isLinear); | |
| if (success) | |
| { | |
| m_polys = polys; | |
| } | |
| } | |
| // The mesh is fill-rule-independent; the fill rule only filters it at | |
| // output, so it's supplied per call rather than baked in. This lets one | |
| // triangulator be cached and reused regardless of fill rule. | |
| size_t maxVertexCount(FillRule fillRule) const | |
| { | |
| return m_polys != nullptr ? countMaxTriangleVertices(m_polys, fillRule) : 0; | |
| } | |
| // Emits the interior triangulation as weight-expanded retrofitted cubic | |
| // patches, merging into patches of up to 3 edge-adjacent triangles. | |
| // Returns the number of patches emitted. | |
| size_t polysToRetrofitCubicPatches( | |
| FillRule fillRule, | |
| gpu::WindingFaces windingFaces, | |
| const RetrofitCubicPatchEmitter& emitPatch) const | |
| { | |
| if (m_polys == nullptr) | |
| { | |
| return 0; | |
| } | |
| return GrTriangulator::polysToRetrofitCubicPatches( | |
| m_polys, | |
| fillRule, | |
| windingFaces, | |
| emitPatch); | |
| } | |
| // Number of patches polysToRetrofitCubicPatches() emits for this | |
| // triangulation. Lazily computed and cached because it requires the full | |
| // (nontrivial) triangle traversal and shared-edge detection. | |
| size_t retrofitCubicPatchCount(FillRule fillRule) const | |
| { | |
| std::optional<size_t>& cached = fillRule == FillRule::evenOdd | |
| ? m_evenOddPatchCount | |
| : m_nonZeroPatchCount; | |
| if (!cached.has_value()) | |
| { | |
| cached = polysToRetrofitCubicPatches( | |
| fillRule, | |
| gpu::WindingFaces::all, | |
| [](const Vec2D*, size_t) {}); | |
| } | |
| return *cached; | |
| } | |
| size_t polysToTriangles( | |
| uint16_t pathID, | |
| FillRule fillRule, | |
| bool reverseTriangles, | |
| bool negateWinding, | |
| gpu::WindingFaces windingFaces, | |
| gpu::WriteOnlyMappedMemory<gpu::TriangleVertex>* mappedMemory) const | |
| { | |
| if (m_polys == nullptr) | |
| { | |
| return 0; | |
| } | |
| return GrTriangulator::polysToTriangles( | |
| m_polys, | |
| maxVertexCount(fillRule), | |
| fillRule, | |
| pathID, | |
| reverseTriangles, | |
| negateWinding, | |
| windingFaces, | |
| mappedMemory); | |
| } | |
| const GroutTriangleList& groutList() const { return fBreadcrumbList; } | |
| private: | |
| Poly* m_polys = nullptr; | |
| // Lazily-computed retrofitCubicPatchCount() cache: one slot per fill rule | |
| // the triangulator sees (nonZero -- which clockwise maps to -- and | |
| // evenOdd). | |
| mutable std::optional<size_t> m_nonZeroPatchCount; | |
| mutable std::optional<size_t> m_evenOddPatchCount; | |
| }; | |
| } // namespace rive | |
| #else | |
| // Stub out GrInnerFanTriangulator::GroutTriangleList for function declarations. | |
| namespace GrInnerFanTriangulator | |
| { | |
| struct GroutTriangleList | |
| { | |
| GroutTriangleList() = delete; | |
| }; | |
| }; // namespace GrInnerFanTriangulator | |
| #endif // SK_ENABLE_OPTIMIZE_SIZE | |
| #endif // GrInnerFanTriangulator_DEFINED |