| /* | |
| * Copyright 2022 Rive | |
| */ | |
| #pragma once | |
| #include "rive/math/raw_path.hpp" | |
| #include "rive/renderer.hpp" | |
| #include "rive/pls/pls.hpp" | |
| #include "rive/pls/pls_draw.hpp" | |
| #include "rive/pls/pls_render_context.hpp" | |
| #include <vector> | |
| namespace rive | |
| { | |
| class GrInnerFanTriangulator; | |
| }; | |
| namespace rive::pls | |
| { | |
| class PLSPath; | |
| class PLSPaint; | |
| class PLSRenderContext; | |
| // Renderer implementation for Rive's pixel local storage renderer. | |
| class PLSRenderer : public Renderer | |
| { | |
| public: | |
| PLSRenderer(PLSRenderContext*); | |
| ~PLSRenderer() override; | |
| void save() override; | |
| void restore() override; | |
| void transform(const Mat2D& matrix) override; | |
| void drawPath(RenderPath*, RenderPaint*) override; | |
| void clipPath(RenderPath*) override; | |
| void drawImage(const RenderImage*, BlendMode, float opacity) override; | |
| void drawImageMesh(const RenderImage*, | |
| rcp<RenderBuffer> vertices_f32, | |
| rcp<RenderBuffer> uvCoords_f32, | |
| rcp<RenderBuffer> indices_u16, | |
| uint32_t vertexCount, | |
| uint32_t indexCount, | |
| BlendMode, | |
| float opacity) override; | |
| // Determines if a path is an axis-aligned rectangle that can be represented by rive::AABB. | |
| static bool IsAABB(const RawPath&, AABB* result); | |
| #ifdef TESTING | |
| bool hasClipRect() const { return m_stack.back().clipRectInverseMatrix != nullptr; } | |
| const AABB& getClipRect() const { return m_stack.back().clipRect; } | |
| const Mat2D& getClipRectMatrix() const { return m_stack.back().clipRectMatrix; } | |
| #endif | |
| private: | |
| void clipRectImpl(AABB, const PLSPath* originalPath); | |
| void clipPathImpl(const PLSPath*); | |
| // Clips and pushes the given draw to m_context. If the clipped draw is too complex to be | |
| // supported by the GPU buffers, even after a logical flush, then nothing is drawn. | |
| void clipAndPushDraw(PLSDrawUniquePtr); | |
| // Pushes any necessary clip updates to m_internalDrawBatch and sets the PLSDraw's clipID and | |
| // clipRectInverseMatrix, if any. | |
| // Returns false if the operation failed, at which point the caller should issue a logical flush | |
| // and try again. | |
| [[nodiscard]] bool applyClip(PLSDraw*); | |
| struct RenderState | |
| { | |
| Mat2D matrix; | |
| size_t clipStackHeight = 0; | |
| AABB clipRect; | |
| Mat2D clipRectMatrix; | |
| const pls::ClipRectInverseMatrix* clipRectInverseMatrix = nullptr; | |
| bool clipIsEmpty = false; | |
| }; | |
| std::vector<RenderState> m_stack{1}; | |
| struct ClipElement | |
| { | |
| ClipElement() = default; | |
| ClipElement(const Mat2D&, const PLSPath*, FillRule); | |
| ~ClipElement(); | |
| void reset(const Mat2D&, const PLSPath*, FillRule); | |
| bool isEquivalent(const Mat2D&, const PLSPath*) const; | |
| Mat2D matrix; | |
| uint64_t rawPathMutationID; | |
| AABB pathBounds; | |
| rcp<const PLSPath> path; | |
| FillRule fillRule; // Bc PLSPath fillRule can mutate during the artboard draw process. | |
| uint32_t clipID; | |
| }; | |
| std::vector<ClipElement> m_clipStack; | |
| PLSRenderContext* const m_context; | |
| std::vector<PLSDrawUniquePtr> m_internalDrawBatch; | |
| // Path of the rectangle [0, 0, 1, 1]. Used to draw images. | |
| rcp<PLSPath> m_unitRectPath; | |
| // Used to build coarse path interiors for the "interior triangulation" algorithm. | |
| RawPath m_scratchPath; | |
| }; | |
| } // namespace rive::pls |