blob: 838684f572ce174638817be22f6d07a9a26227e3 [file] [log] [blame]
/*
* 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<GeometryNode>);
~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<GeometryNode>&) = 0;
private:
const sk_sp<GeometryNode> 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<TrimEffect> Make(sk_sp<GeometryNode> child) {
return child ? sk_sp<TrimEffect>(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<GeometryNode> child) : INHERITED(std::move(child)) {}
SkPath onRevalidateEffect(const sk_sp<GeometryNode>&) 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<GeometryTransform> Make(sk_sp<GeometryNode> child, sk_sp<Transform> transform) {
return child && transform
? sk_sp<GeometryTransform>(new GeometryTransform(std::move(child),
std::move(transform)))
: nullptr;
}
~GeometryTransform() override;
const sk_sp<Transform>& getTransform() const { return fTransform; }
private:
GeometryTransform(sk_sp<GeometryNode>, sk_sp<Transform>);
SkPath onRevalidateEffect(const sk_sp<GeometryNode>&) override;
const sk_sp<Transform> 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<DashEffect> Make(sk_sp<GeometryNode> child) {
return child ? sk_sp<DashEffect>(new DashEffect(std::move(child))) : nullptr;
}
SG_ATTRIBUTE(Intervals, std::vector<float>, fIntervals)
SG_ATTRIBUTE(Phase, float , fPhase )
private:
explicit DashEffect(sk_sp<GeometryNode> child) : INHERITED(std::move(child)) {}
SkPath onRevalidateEffect(const sk_sp<GeometryNode>&) override;
std::vector<float> 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<RoundEffect> Make(sk_sp<GeometryNode> child) {
return child ? sk_sp<RoundEffect>(new RoundEffect(std::move(child))) : nullptr;
}
SG_ATTRIBUTE(Radius, SkScalar, fRadius)
private:
explicit RoundEffect(sk_sp<GeometryNode> child) : INHERITED(std::move(child)) {}
SkPath onRevalidateEffect(const sk_sp<GeometryNode>&) override;
SkScalar fRadius = 0;
using INHERITED = GeometryEffect;
};
/**
* Apply an offset effect to the child geometry.
*/
class OffsetEffect final : public GeometryEffect {
public:
static sk_sp<OffsetEffect> Make(sk_sp<GeometryNode> child) {
return child ? sk_sp<OffsetEffect>(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<GeometryNode> child) : INHERITED(std::move(child)) {}
SkPath onRevalidateEffect(const sk_sp<GeometryNode>&) override;
SkScalar fOffset = 0,
fMiterLimit = 4;
SkPaint::Join fJoin = SkPaint::kMiter_Join;
using INHERITED = GeometryEffect;
};
} // namespace sksg
#endif // SkSGGeometryEffect_DEFINED