You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
171 lines
4.9 KiB
171 lines
4.9 KiB
/*
|
|
* 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
|