| #ifndef _RIVE_PATH_HPP_ |
| #define _RIVE_PATH_HPP_ |
| #include "rive/command_path.hpp" |
| #include "rive/generated/shapes/path_base.hpp" |
| #include "rive/math/mat2d.hpp" |
| #include "rive/math/raw_path.hpp" |
| #include "rive/shapes/shape_paint_container.hpp" |
| #include <vector> |
| |
| namespace rive |
| { |
| class Shape; |
| class PathVertex; |
| class RenderPathDeformer; |
| |
| #ifdef ENABLE_QUERY_FLAT_VERTICES |
| /// Optionally compiled in for tools that need to compute per frame world |
| /// transformed path vertices. These should not be used at runtime as it's |
| /// not optimized for performance (it does a lot of memory allocation). |
| |
| /// A flattened path is composed of only linear |
| /// and cubic vertices. No corner vertices and it's entirely in world space. |
| /// This is helpful for getting a close to identical representation of the |
| /// vertices used to issue the high level path draw commands. |
| class FlattenedPath |
| { |
| private: |
| std::vector<PathVertex*> m_Vertices; |
| |
| public: |
| ~FlattenedPath(); |
| |
| const std::vector<PathVertex*>& vertices() const { return m_Vertices; } |
| void addVertex(PathVertex* vertex, const Mat2D& transform); |
| }; |
| #endif |
| |
| class Path : public PathBase |
| { |
| protected: |
| Shape* m_Shape = nullptr; |
| std::vector<PathVertex*> m_Vertices; |
| bool m_deferredPathDirt = false; |
| PathFlags m_pathFlags = PathFlags::none; |
| RawPath m_rawPath; |
| RenderPathDeformer* deformer() const; |
| void isHoleChanged() override; |
| |
| public: |
| static float computeIdealControlPointDistance(const Vec2D& toPrev, |
| const Vec2D& toNext, |
| float radius); |
| |
| static void addRoundedRect(RawPath& rawPath, |
| const AABB& bounds, |
| float topLeft, |
| float topRight, |
| float bottomRight, |
| float bottomLeft); |
| |
| Shape* shape() const { return m_Shape; } |
| StatusCode onAddedClean(CoreContext* context) override; |
| void buildDependencies() override; |
| virtual const Mat2D& pathTransform() const; |
| bool collapse(bool value) override; |
| const RawPath& rawPath() const { return m_rawPath; } |
| // True while m_rawPath has yet to be rebuilt for pending changes: the Path |
| // dirt is still queued, or the build was deferred. Layout runs before |
| // Path::update in the update pass, so a measure can land here first and |
| // must build its own copy rather than read a stale/empty rawPath. |
| bool needsPathBuild() const |
| { |
| return hasDirt(ComponentDirt::Path) || m_deferredPathDirt; |
| } |
| // Bounds in this path's own space derived from its properties rather than |
| // its built geometry, for callers that run before update() has positioned |
| // vertices. A ParametricPath knows its box up front; anything vertex-driven |
| // returns false and must be measured from geometry. |
| virtual bool tryPropertyBounds(AABB& result) const { return false; } |
| void update(ComponentDirt value) override; |
| |
| void addFlags(PathFlags flags); |
| bool isFlagged(PathFlags flags) const; |
| |
| bool canDeferPathUpdate(); |
| void addVertex(PathVertex* vertex); |
| void popVertex(); |
| |
| virtual void markPathDirty(bool sendToLayout = true); |
| virtual bool isPathClosed() const { return true; } |
| void onDirty(ComponentDirt dirt) override; |
| inline bool isHidden() const { return (pathFlags() & 0x1) == 0x1; } |
| #ifdef ENABLE_QUERY_FLAT_VERTICES |
| FlattenedPath* makeFlat(bool transformToParent); |
| #endif |
| |
| #ifdef TESTING |
| std::vector<PathVertex*>& vertices() { return m_Vertices; } |
| #endif |
| |
| void buildPath(RawPath&) const; |
| AABB localBounds() const override; |
| }; |
| } // namespace rive |
| |
| #endif |