Update Factory::makeRenderPath to only accept a RawPath Deletes the version that takes spans of points and verbs. We are planning to inject the implicit moveTos into RawPath, at which point we won't be able to just copy in arrays of points and verbs anymore. Also changes the "RawPath" version of the factory method to take a non-const "RawPath&" ref. This enables zero-copy construction via stealing the arrays out from under the RawPath's points and verbs. Diffs= 1bd616612 Update Factory::makeRenderPath to only accept a RawPath (#4211)
diff --git a/.rive_head b/.rive_head index 54ed701..700dbe4 100644 --- a/.rive_head +++ b/.rive_head
@@ -1 +1 @@ -38b70a98dd197e4bd59e2fca22f3d9e5b26f2dfb +1bd6166123b7fac75106099f5e28568b3f292143
diff --git a/include/rive/factory.hpp b/include/rive/factory.hpp index 3ee59a8..f60aeec 100644 --- a/include/rive/factory.hpp +++ b/include/rive/factory.hpp
@@ -18,6 +18,8 @@ namespace rive { +class RawPath; + class Factory { public: Factory() {} @@ -43,9 +45,9 @@ size_t count) = 0; // Returns a full-formed RenderPath -- can be treated as immutable - virtual std::unique_ptr<RenderPath> makeRenderPath(Span<const Vec2D> points, - Span<const PathVerb> verbs, - FillRule) = 0; + // This call might swap out the arrays backing the points and verbs in the given RawPath, so the + // caller can expect it to be in an undefined state upon return. + virtual std::unique_ptr<RenderPath> makeRenderPath(RawPath&, FillRule) = 0; // Deprecated -- working to make RenderPath's immutable virtual std::unique_ptr<RenderPath> makeEmptyRenderPath() = 0; @@ -59,7 +61,6 @@ // Non-virtual helpers std::unique_ptr<RenderPath> makeRenderPath(const AABB&); - std::unique_ptr<RenderPath> makeRenderPath(const RawPath&, FillRule); }; } // namespace rive
diff --git a/include/rive/math/raw_path.hpp b/include/rive/math/raw_path.hpp index fea2032..41ac2b4 100644 --- a/include/rive/math/raw_path.hpp +++ b/include/rive/math/raw_path.hpp
@@ -25,10 +25,6 @@ std::vector<Vec2D> m_Points; std::vector<PathVerb> m_Verbs; - // Construct a RawPath from count points and verbs. - RawPath(Span<const Vec2D> points, Span<const PathVerb> verbs); - RawPath() {} - bool operator==(const RawPath& o) const; bool operator!=(const RawPath& o) const { return !(*this == o); } @@ -41,6 +37,8 @@ void cubic(Vec2D, Vec2D, Vec2D); void close(); + void swap(RawPath&); + // Makes the path empty and frees any memory allocated by the drawing // (line, curve, move, close) calls. void reset();
diff --git a/include/utils/no_op_factory.hpp b/include/utils/no_op_factory.hpp index ea8a6aa..2c1261c 100644 --- a/include/utils/no_op_factory.hpp +++ b/include/utils/no_op_factory.hpp
@@ -29,9 +29,7 @@ const float stops[], // [count] size_t count) override; - std::unique_ptr<RenderPath> makeRenderPath(Span<const Vec2D> points, - Span<const PathVerb> verbs, - FillRule) override; + std::unique_ptr<RenderPath> makeRenderPath(RawPath&, FillRule) override; std::unique_ptr<RenderPath> makeEmptyRenderPath() override;
diff --git a/skia/renderer/include/cg_factory.hpp b/skia/renderer/include/cg_factory.hpp index bcc44a2..140a7f0 100644 --- a/skia/renderer/include/cg_factory.hpp +++ b/skia/renderer/include/cg_factory.hpp
@@ -31,9 +31,7 @@ const float stops[], // [count] size_t count) override; - std::unique_ptr<RenderPath> makeRenderPath(Span<const Vec2D> points, - Span<const PathVerb> verbs, - FillRule) override; + std::unique_ptr<RenderPath> makeRenderPath(RawPath&, FillRule) override; std::unique_ptr<RenderPath> makeEmptyRenderPath() override;
diff --git a/skia/renderer/include/skia_factory.hpp b/skia/renderer/include/skia_factory.hpp index 3194759..af7f9aa 100644 --- a/skia/renderer/include/skia_factory.hpp +++ b/skia/renderer/include/skia_factory.hpp
@@ -31,9 +31,7 @@ const float stops[], // [count] size_t count) override; - std::unique_ptr<RenderPath> makeRenderPath(Span<const Vec2D> points, - Span<const PathVerb> verbs, - FillRule) override; + std::unique_ptr<RenderPath> makeRenderPath(RawPath&, FillRule) override; std::unique_ptr<RenderPath> makeEmptyRenderPath() override;
diff --git a/skia/renderer/src/cg_factory.cpp b/skia/renderer/src/cg_factory.cpp index dc68d15..5deea2a 100644 --- a/skia/renderer/src/cg_factory.cpp +++ b/skia/renderer/src/cg_factory.cpp
@@ -464,10 +464,8 @@ new CGRadialGradientRenderShader(cx, cy, radius, colors, stops, count)); } -std::unique_ptr<RenderPath> CGFactory::makeRenderPath(Span<const Vec2D> points, - Span<const PathVerb> verbs, - FillRule fillRule) { - return std::make_unique<CGRenderPath>(points, verbs, fillRule); +std::unique_ptr<RenderPath> CGFactory::makeRenderPath(RawPath& rawPath, FillRule fillRule) { + return std::make_unique<CGRenderPath>(rawPath.points(), rawPath.verbs(), fillRule); } std::unique_ptr<RenderPath> CGFactory::makeEmptyRenderPath() {
diff --git a/skia/renderer/src/skia_factory.cpp b/skia/renderer/src/skia_factory.cpp index a8ecc6a..9e8a56b 100644 --- a/skia/renderer/src/skia_factory.cpp +++ b/skia/renderer/src/skia_factory.cpp
@@ -242,17 +242,15 @@ return rcp<RenderShader>(new SkiaRenderShader(std::move(sh))); } -std::unique_ptr<RenderPath> SkiaFactory::makeRenderPath(Span<const Vec2D> points, - Span<const PathVerb> verbs, - FillRule fillRule) { +std::unique_ptr<RenderPath> SkiaFactory::makeRenderPath(RawPath& rawPath, FillRule fillRule) { const bool isVolatile = false; // ??? const SkScalar* conicWeights = nullptr; const int conicWeightCount = 0; return std::make_unique<SkiaRenderPath>( - SkPath::Make(reinterpret_cast<const SkPoint*>(points.data()), - points.count(), - (uint8_t*)verbs.data(), - verbs.count(), + SkPath::Make(reinterpret_cast<const SkPoint*>(rawPath.m_Points.data()), + rawPath.m_Points.size(), + (uint8_t*)rawPath.m_Verbs.data(), + rawPath.m_Verbs.size(), conicWeights, conicWeightCount, ToSkia::convert(fillRule),
diff --git a/src/factory.cpp b/src/factory.cpp index 693a287..2bf02a8 100644 --- a/src/factory.cpp +++ b/src/factory.cpp
@@ -9,22 +9,7 @@ using namespace rive; std::unique_ptr<RenderPath> Factory::makeRenderPath(const AABB& r) { - const Vec2D pts[] = { - {r.left(), r.top()}, - {r.right(), r.top()}, - {r.right(), r.bottom()}, - {r.left(), r.bottom()}, - }; - const PathVerb verbs[] = { - PathVerb::move, - PathVerb::line, - PathVerb::line, - PathVerb::line, - PathVerb::close, - }; - return this->makeRenderPath(pts, verbs, FillRule::nonZero); -} - -std::unique_ptr<RenderPath> Factory::makeRenderPath(const RawPath& rp, FillRule fill) { - return this->makeRenderPath(rp.points(), rp.verbs(), fill); + RawPath rawPath; + rawPath.addRect(r); + return makeRenderPath(rawPath, FillRule::nonZero); }
diff --git a/src/math/raw_path.cpp b/src/math/raw_path.cpp index 161f15b..40e821f 100644 --- a/src/math/raw_path.cpp +++ b/src/math/raw_path.cpp
@@ -12,9 +12,6 @@ namespace rive { -RawPath::RawPath(Span<const Vec2D> points, Span<const PathVerb> verbs) : - m_Points(points.begin(), points.end()), m_Verbs(verbs.begin(), verbs.end()) {} - bool RawPath::operator==(const RawPath& o) const { return m_Points == o.m_Points && m_Verbs == o.m_Verbs; } @@ -226,6 +223,11 @@ m_currPts -= n; } +void RawPath::swap(RawPath& rawPath) { + m_Points.swap(rawPath.m_Points); + m_Verbs.swap(rawPath.m_Verbs); +} + void RawPath::reset() { m_Points.clear(); m_Points.shrink_to_fit();
diff --git a/tess/include/rive/tess/sokol/sokol_factory.hpp b/tess/include/rive/tess/sokol/sokol_factory.hpp index 062e21b..93b8b27 100644 --- a/tess/include/rive/tess/sokol/sokol_factory.hpp +++ b/tess/include/rive/tess/sokol/sokol_factory.hpp
@@ -34,9 +34,7 @@ size_t count) override; // Returns a full-formed RenderPath -- can be treated as immutable - std::unique_ptr<RenderPath> makeRenderPath(Span<const Vec2D> points, - Span<const PathVerb> verbs, - FillRule) override; + std::unique_ptr<RenderPath> makeRenderPath(RawPath&, FillRule) override; std::unique_ptr<RenderPath> makeEmptyRenderPath() override;
diff --git a/tess/include/rive/tess/tess_render_path.hpp b/tess/include/rive/tess/tess_render_path.hpp index f1c18f9..a3e24ec 100644 --- a/tess/include/rive/tess/tess_render_path.hpp +++ b/tess/include/rive/tess/tess_render_path.hpp
@@ -39,7 +39,7 @@ public: TessRenderPath(); - TessRenderPath(Span<const Vec2D> points, Span<const PathVerb> verbs, FillRule fillRule); + TessRenderPath(RawPath&, FillRule); ~TessRenderPath(); void reset() override; void fillRule(FillRule value) override; @@ -65,4 +65,4 @@ const RawPath& rawPath() const; }; } // namespace rive -#endif \ No newline at end of file +#endif
diff --git a/tess/src/sokol/sokol_tess_renderer.cpp b/tess/src/sokol/sokol_tess_renderer.cpp index e968d89..f37539e 100644 --- a/tess/src/sokol/sokol_tess_renderer.cpp +++ b/tess/src/sokol/sokol_tess_renderer.cpp
@@ -17,8 +17,7 @@ class SokolRenderPath : public TessRenderPath { public: SokolRenderPath() {} - SokolRenderPath(Span<const Vec2D> points, Span<const PathVerb> verbs, FillRule fillRule) : - TessRenderPath(points, verbs, fillRule) {} + SokolRenderPath(RawPath& rawPath, FillRule fillRule) : TessRenderPath(rawPath, fillRule) {} ~SokolRenderPath() { sg_destroy_buffer(m_vertexBuffer); @@ -125,10 +124,8 @@ }; // Returns a full-formed RenderPath -- can be treated as immutable -std::unique_ptr<RenderPath> SokolFactory::makeRenderPath(Span<const Vec2D> points, - Span<const PathVerb> verbs, - FillRule rule) { - return std::make_unique<SokolRenderPath>(points, verbs, rule); +std::unique_ptr<RenderPath> SokolFactory::makeRenderPath(RawPath& rawPath, FillRule rule) { + return std::make_unique<SokolRenderPath>(rawPath, rule); } std::unique_ptr<RenderPath> SokolFactory::makeEmptyRenderPath() { @@ -989,4 +986,4 @@ SokolRenderImage::~SokolRenderImage() { sg_destroy_buffer(m_vertexBuffer); sg_destroy_buffer(m_uvBuffer); -} \ No newline at end of file +}
diff --git a/tess/src/tess_render_path.cpp b/tess/src/tess_render_path.cpp index 7cdd6cb..0ed6c45 100644 --- a/tess/src/tess_render_path.cpp +++ b/tess/src/tess_render_path.cpp
@@ -6,10 +6,10 @@ using namespace rive; TessRenderPath::TessRenderPath() : m_segmentedContour(contourThreshold) {} -TessRenderPath::TessRenderPath(Span<const Vec2D> points, - Span<const PathVerb> verbs, - FillRule fillRule) : - m_rawPath(points, verbs), m_fillRule(fillRule), m_segmentedContour(contourThreshold) {} +TessRenderPath::TessRenderPath(RawPath& rawPath, FillRule fillRule) : + m_fillRule(fillRule), m_segmentedContour(contourThreshold) { + m_rawPath.swap(rawPath); +} TessRenderPath::~TessRenderPath() {}
diff --git a/test/raw_path_test.cpp b/test/raw_path_test.cpp index 0bcd67b..7b77337 100644 --- a/test/raw_path_test.cpp +++ b/test/raw_path_test.cpp
@@ -299,29 +299,6 @@ } } -TEST_CASE("factory", "[rawpath]") { - // clang-format off - const Vec2D pts[] = { - {1, 2}, - {2, 3}, - {4, 5}, {6, 7}, {8, 9}, - }; - const PathVerb vbs[] = { - PathVerb::move, PathVerb::line, PathVerb::cubic, PathVerb::close - }; - // clang-format on - - RawPath path0(pts, vbs); - - RawPath path1; - path1.move(pts[0]); - path1.line(pts[1]); - path1.cubic(pts[2], pts[3], pts[4]); - path1.close(); - - REQUIRE(path0 == path1); -} - TEST_CASE("bounds", "[rawpath]") { RawPath path; AABB bounds;
diff --git a/utils/no_op_factory.cpp b/utils/no_op_factory.cpp index ab6ebbd..c187a46 100644 --- a/utils/no_op_factory.cpp +++ b/utils/no_op_factory.cpp
@@ -58,9 +58,7 @@ return nullptr; } -std::unique_ptr<RenderPath> NoOpFactory::makeRenderPath(Span<const Vec2D> points, - Span<const PathVerb> verbs, - FillRule) { +std::unique_ptr<RenderPath> NoOpFactory::makeRenderPath(RawPath&, FillRule) { return std::make_unique<NoOpRenderPath>(); }
diff --git a/viewer/src/viewer_content/text_content.cpp b/viewer/src/viewer_content/text_content.cpp index 2d97a0d..94a9472 100644 --- a/viewer/src/viewer_content/text_content.cpp +++ b/viewer/src/viewer_content/text_content.cpp
@@ -5,6 +5,7 @@ #include "viewer/viewer_content.hpp" #include "utils/rive_utf.hpp" +#include "rive/math/raw_path.hpp" #include "rive/factory.hpp" #include "rive/refcnt.hpp" #include "rive/render_text.hpp" @@ -116,9 +117,10 @@ static std::unique_ptr<rive::RenderPath> make_line(rive::Factory* factory, rive::Vec2D a, rive::Vec2D b) { - rive::Vec2D pts[] = {a, b}; - rive::PathVerb vbs[] = {rive::PathVerb::move, rive::PathVerb::line}; - return factory->makeRenderPath(pts, vbs, rive::FillRule::nonZero); + rive::RawPath rawPath; + rawPath.move(a); + rawPath.line(b); + return factory->makeRenderPath(rawPath, rive::FillRule::nonZero); } static void draw_line(rive::Factory* factory, rive::Renderer* renderer, float x) {
diff --git a/viewer/src/viewer_content/textpath_content.cpp b/viewer/src/viewer_content/textpath_content.cpp index 83b1051..4495446 100644 --- a/viewer/src/viewer_content/textpath_content.cpp +++ b/viewer/src/viewer_content/textpath_content.cpp
@@ -5,6 +5,7 @@ #include "viewer/viewer_content.hpp" #include "utils/rive_utf.hpp" +#include "rive/math/raw_path.hpp" #include "rive/refcnt.hpp" #include "rive/factory.hpp" #include "rive/render_text.hpp" @@ -59,11 +60,11 @@ //////////////////////////////////////////////////////////////////////////////////// -static std::unique_ptr<RenderPath> make_rpath(const RawPath& path) { +static std::unique_ptr<RenderPath> make_rpath(RawPath& path) { return ViewerContent::RiveFactory()->makeRenderPath(path, FillRule::nonZero); } -static void stroke_path(Renderer* renderer, const RawPath& path, float size, ColorInt color) { +static void stroke_path(Renderer* renderer, RawPath& path, float size, ColorInt color) { auto paint = ViewerContent::RiveFactory()->makeRenderPaint(); paint->color(color); paint->thickness(size); @@ -178,7 +179,7 @@ m_trans = Mat2D::fromTranslate(200, 200) * Mat2D::fromScale(2, 2); } - void draw_warp(Renderer* renderer, const RawPath& warp) { + void draw_warp(Renderer* renderer, RawPath& warp) { stroke_path(renderer, warp, 0.5, 0xFF00FF00); auto paint = ViewerContent::RiveFactory()->makeRenderPaint(); @@ -285,8 +286,8 @@ }); }; - visit(m_gruns, {0, 0}, [&](const RawPath& rp) { - const RawPath* ptr = &rp; + visit(m_gruns, {0, 0}, [&](RawPath& rp) { + RawPath* ptr = &rp; RawPath storage; if (m_trackingOneLine) { storage = wrap_path(rp, m_oneLineX, m_flareRadius);
diff --git a/viewer/src/viewer_content/trimpath_content.cpp b/viewer/src/viewer_content/trimpath_content.cpp index f5f321c..760bb9c 100644 --- a/viewer/src/viewer_content/trimpath_content.cpp +++ b/viewer/src/viewer_content/trimpath_content.cpp
@@ -32,11 +32,11 @@ //////////////////////////////////////////////////////////////////////////////////// -static std::unique_ptr<RenderPath> make_rpath(const RawPath& path) { +static std::unique_ptr<RenderPath> make_rpath(RawPath& path) { return ViewerContent::RiveFactory()->makeRenderPath(path, FillRule::nonZero); } -static void stroke_path(Renderer* renderer, const RawPath& path, float size, ColorInt color) { +static void stroke_path(Renderer* renderer, RawPath& path, float size, ColorInt color) { auto paint = ViewerContent::RiveFactory()->makeRenderPaint(); paint->color(color); paint->thickness(size); @@ -90,7 +90,7 @@ cubicpath.cubic(m_pathpts[1], m_pathpts[2], m_pathpts[3]); cubicpath.line(m_pathpts[4]); - const RawPath* ps[] = {&path, &cubicpath}; + RawPath* ps[] = {&path, &cubicpath}; renderer->save(); for (auto p : ps) {