/* * Copyright 2020 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef SkSGGeometryEffect_DEFINED #define SkSGGeometryEffect_DEFINED #include "modules/sksg/include/SkSGGeometryNode.h" #include "include/core/SkPaint.h" #include "include/core/SkPath.h" #include "include/effects/SkTrimPathEffect.h" #include "modules/sksg/include/SkSGTransform.h" namespace sksg { /** * Base class for geometry effects. */ class GeometryEffect : public GeometryNode { protected: explicit GeometryEffect(sk_sp); ~GeometryEffect() override; void onClip(SkCanvas*, bool antiAlias) const final; void onDraw(SkCanvas*, const SkPaint&) const final; bool onContains(const SkPoint&) const final; SkRect onRevalidate(InvalidationController*, const SkMatrix&) final; SkPath onAsPath() const final; virtual SkPath onRevalidateEffect(const sk_sp&) = 0; private: const sk_sp fChild; SkPath fPath; // transformed child cache. using INHERITED = GeometryNode; }; /** * Apply a trim effect to the child geometry. */ class TrimEffect final : public GeometryEffect { public: static sk_sp Make(sk_sp child) { return child ? sk_sp(new TrimEffect(std::move(child))) : nullptr; } SG_ATTRIBUTE(Start , SkScalar , fStart ) SG_ATTRIBUTE(Stop , SkScalar , fStop ) SG_ATTRIBUTE(Mode , SkTrimPathEffect::Mode, fMode ) private: explicit TrimEffect(sk_sp child) : INHERITED(std::move(child)) {} SkPath onRevalidateEffect(const sk_sp&) override; SkScalar fStart = 0, fStop = 1; SkTrimPathEffect::Mode fMode = SkTrimPathEffect::Mode::kNormal; using INHERITED = GeometryEffect; }; /** * Apply a transform to a GeometryNode. */ class GeometryTransform final : public GeometryEffect { public: static sk_sp Make(sk_sp child, sk_sp transform) { return child && transform ? sk_sp(new GeometryTransform(std::move(child), std::move(transform))) : nullptr; } ~GeometryTransform() override; const sk_sp& getTransform() const { return fTransform; } private: GeometryTransform(sk_sp, sk_sp); SkPath onRevalidateEffect(const sk_sp&) override; const sk_sp fTransform; using INHERITED = GeometryEffect; }; /** * Apply a dash effect to the child geometry. * * Follows the same semantics as SkDashPathEffect, with one minor tweak: when the number of * intervals is odd, they are repeated once more to attain an even sequence (same as SVG * stroke-dasharray: https://www.w3.org/TR/SVG11/painting.html#StrokeDasharrayProperty). */ class DashEffect final : public GeometryEffect { public: static sk_sp Make(sk_sp child) { return child ? sk_sp(new DashEffect(std::move(child))) : nullptr; } SG_ATTRIBUTE(Intervals, std::vector, fIntervals) SG_ATTRIBUTE(Phase, float , fPhase ) private: explicit DashEffect(sk_sp child) : INHERITED(std::move(child)) {} SkPath onRevalidateEffect(const sk_sp&) override; std::vector fIntervals; float fPhase = 0; using INHERITED = GeometryEffect; }; /** * Apply a rounded-corner effect to the child geometry. */ class RoundEffect final : public GeometryEffect { public: static sk_sp Make(sk_sp child) { return child ? sk_sp(new RoundEffect(std::move(child))) : nullptr; } SG_ATTRIBUTE(Radius, SkScalar, fRadius) private: explicit RoundEffect(sk_sp child) : INHERITED(std::move(child)) {} SkPath onRevalidateEffect(const sk_sp&) override; SkScalar fRadius = 0; using INHERITED = GeometryEffect; }; /** * Apply an offset effect to the child geometry. */ class OffsetEffect final : public GeometryEffect { public: static sk_sp Make(sk_sp child) { return child ? sk_sp(new OffsetEffect(std::move(child))) : nullptr; } SG_ATTRIBUTE(Offset , SkScalar , fOffset ) SG_ATTRIBUTE(MiterLimit , SkScalar , fMiterLimit) SG_ATTRIBUTE(Join , SkPaint::Join, fJoin ) private: explicit OffsetEffect(sk_sp child) : INHERITED(std::move(child)) {} SkPath onRevalidateEffect(const sk_sp&) override; SkScalar fOffset = 0, fMiterLimit = 4; SkPaint::Join fJoin = SkPaint::kMiter_Join; using INHERITED = GeometryEffect; }; } // namespace sksg #endif // SkSGGeometryEffect_DEFINED