| #ifndef _RIVE_PATH_COMPOSER_HPP_ | |
| #define _RIVE_PATH_COMPOSER_HPP_ | |
| #include "rive/component.hpp" | |
| #include "rive/shapes/shape_paint_path.hpp" | |
| #include "rive/refcnt.hpp" | |
| #include "rive/math/aabb.hpp" | |
| #include "rive/math/raw_path.hpp" | |
| #include "rive/shapes/path_flags.hpp" | |
| #include <cmath> | |
| #include <vector> | |
| namespace rive | |
| { | |
| class Shape; | |
| class CommandPath; | |
| class PathComposer : public Component | |
| { | |
| public: | |
| PathComposer(Shape* shape); | |
| Shape* shape() const { return m_shape; } | |
| void buildDependencies() override; | |
| void onDirty(ComponentDirt dirt) override; | |
| void update(ComponentDirt value) override; | |
| ShapePaintPath* localPath() { return &m_localPath; } | |
| ShapePaintPath* worldPath() { return &m_worldPath; } | |
| ShapePaintPath* localClockwisePath() { return &m_localClockwisePath; } | |
| void pathCollapseChanged(); | |
| // The inputs a local path is built from, per path, as of the last build. | |
| struct LocalPathInput | |
| { | |
| Mat2D transform; | |
| uint32_t geometryVersion; | |
| bool skipped; | |
| float linearTolerance; | |
| float translationTolerance; | |
| // The composed transform is inverseWorld * pathTransform, so it | |
| // carries the rounding of an A^-1 * A round trip: bit equality never | |
| // holds for a shape that has moved, even though the exact result is | |
| // unchanged. The two halves drift at different scales, so they get | |
| // separate tolerances, and both are compared against the transform the | |
| // buffer was actually built from -- which is what keeps the error | |
| // bounded by the tolerance instead of accumulating frame over frame. | |
| bool matches(const LocalPathInput& o) const | |
| { | |
| if (geometryVersion != o.geometryVersion || skipped != o.skipped) | |
| { | |
| return false; | |
| } | |
| for (int i = 0; i < 4; i++) | |
| { | |
| if (std::abs(transform[i] - o.transform[i]) > o.linearTolerance) | |
| { | |
| return false; | |
| } | |
| } | |
| return std::abs(transform[4] - o.transform[4]) <= | |
| o.translationTolerance && | |
| std::abs(transform[5] - o.transform[5]) <= o.translationTolerance; | |
| } | |
| }; | |
| bool localInputsChanged(); | |
| // Whether a layout participant's intrinsic bounds -- what its slot is | |
| // measured from -- moved since the layout was last told about them. | |
| bool intrinsicBoundsChanged(); | |
| private: | |
| std::vector<LocalPathInput> m_localInputs; | |
| std::vector<LocalPathInput> m_scratchInputs; | |
| AABB m_reportedIntrinsicBounds; | |
| bool m_hasReportedIntrinsicBounds = false; | |
| PathFlags m_builtLocalFlags = PathFlags::none; | |
| bool m_hasLocalInputs = false; | |
| Shape* m_shape; | |
| ShapePaintPath m_localPath; | |
| ShapePaintPath m_worldPath; | |
| ShapePaintPath m_localClockwisePath; | |
| bool m_deferredPathDirt; | |
| bool m_shapeNotified = false; | |
| }; | |
| } // namespace rive | |
| #endif |