diff --git a/include/tgfx/core/PathEffect.h b/include/tgfx/core/PathEffect.h index 749e6c4..949cc6d 100644 --- a/include/tgfx/core/PathEffect.h +++ b/include/tgfx/core/PathEffect.h @@ -37,8 +37,8 @@ class PathEffect { * @param intervals array containing an even number of entries (>=2), with the even indices * specifying the length of "on" intervals, and the odd indices specifying the length of "off" * intervals. - * @param count number of elements in the intervals array - * @param phase offset into the intervals array (mod the sum of all of the intervals). + * @param count number of elements in the interval array + * @param phase offset into the interval array (mod the sum of all of the intervals). */ static std::unique_ptr MakeDash(const float intervals[], int count, float phase); @@ -49,6 +49,16 @@ class PathEffect { */ static std::unique_ptr MakeCorner(float radius); + /** + * Creates a path effect that returns a segment of the input path based on the given start and + * stop "t" values. The startT and stopT values must be between 0 and 1, inclusive. If they are + * outside this range, they will be clamped to the nearest valid value. If either value is NaN, + * nullptr will be returned. + * @param startT The starting point of the path segment to be returned. + * @param stopT The ending point of the path segment to be returned. + */ + static std::unique_ptr MakeTrim(float startT, float stopT); + virtual ~PathEffect() = default; /** @@ -56,5 +66,12 @@ class PathEffect { * leaves this path unchanged. */ virtual bool filterPath(Path* path) const = 0; + + /** + * Returns the bounds of the path after applying this effect. + */ + virtual Rect filterBounds(const Rect& rect) const { + return rect; + } }; } // namespace tgfx \ No newline at end of file diff --git a/src/core/PathEffect.cpp b/src/core/PathEffect.cpp index a470eb9..e447d5a 100644 --- a/src/core/PathEffect.cpp +++ b/src/core/PathEffect.cpp @@ -17,7 +17,9 @@ ///////////////////////////////////////////////////////////////////////////////////////////////// #include "tgfx/core/PathEffect.h" +#include #include "core/PathRef.h" +#include "tgfx/core/PathMeasure.h" #include "tgfx/core/Stroke.h" namespace tgfx { @@ -54,10 +56,47 @@ class StrokePathEffect : public PathEffect { return paint.getFillPath(skPath, &skPath); } + Rect filterBounds(const Rect& rect) const override { + auto bounds = rect; + auto strokeWidth = paint.getStrokeWidth(); + bounds.outset(strokeWidth, strokeWidth); + return bounds; + } + private: SkPaint paint = {}; }; +class TrimPathEffect : public PathEffect { + public: + TrimPathEffect(float startT, float stopT) : startT(startT), stopT(stopT) { + } + + bool filterPath(Path* path) const override { + if (path == nullptr) { + return false; + } + if (startT >= stopT) { + path->reset(); + return true; + } + auto pathMeasure = PathMeasure::MakeFrom(*path); + auto length = pathMeasure->getLength(); + auto start = startT * length; + auto end = stopT * length; + Path tempPath = {}; + if (!pathMeasure->getSegment(start, end, &tempPath)) { + return false; + } + *path = std::move(tempPath); + return true; + } + + private: + float startT = 0.0f; + float stopT = 1.0f; +}; + static SkPaint::Cap ToSkLineCap(LineCap cap) { switch (cap) { case LineCap::Round: @@ -108,4 +147,17 @@ std::unique_ptr PathEffect::MakeCorner(float radius) { } return std::unique_ptr(new PkPathEffect(std::move(effect))); } + +std::unique_ptr PathEffect::MakeTrim(float startT, float stopT) { + if (isnan(startT) || isnan(stopT)) { + return nullptr; + } + if (startT <= 0 && stopT >= 1) { + return nullptr; + } + startT = std::max(0.f, std::min(startT, 1.f)); + stopT = std::max(0.f, std::min(stopT, 1.f)); + return std::unique_ptr(new TrimPathEffect(startT, stopT)); +} + } // namespace tgfx \ No newline at end of file