From 41dff6ef68fc2a537263e0f59ac811cdbae6ea48 Mon Sep 17 00:00:00 2001 From: Florin Malita Date: Mon, 30 Apr 2018 23:08:15 -0400 Subject: [skottie] Add support for round-corners geometry effects TBR= Change-Id: I5505561df28d5953526662d60fe2300cb112bc37 Reviewed-on: https://skia-review.googlesource.com/124769 Reviewed-by: Florin Malita Commit-Queue: Florin Malita --- experimental/skottie/Skottie.cpp | 22 ++++++++++ experimental/sksg/geometry/SkSGRoundEffect.cpp | 56 ++++++++++++++++++++++++++ experimental/sksg/geometry/SkSGRoundEffect.h | 50 +++++++++++++++++++++++ 3 files changed, 128 insertions(+) create mode 100644 experimental/sksg/geometry/SkSGRoundEffect.cpp create mode 100644 experimental/sksg/geometry/SkSGRoundEffect.h (limited to 'experimental') diff --git a/experimental/skottie/Skottie.cpp b/experimental/skottie/Skottie.cpp index 1b5886eee0..c4e964d4ee 100644 --- a/experimental/skottie/Skottie.cpp +++ b/experimental/skottie/Skottie.cpp @@ -33,6 +33,7 @@ #include "SkSGOpacityEffect.h" #include "SkSGPath.h" #include "SkSGRect.h" +#include "SkSGRoundEffect.h" #include "SkSGScene.h" #include "SkSGTransform.h" #include "SkSGTrimEffect.h" @@ -452,6 +453,25 @@ std::vector> AttachTrimGeometryEffect( return trimmed; } +std::vector> AttachRoundGeometryEffect( + const Json::Value& jtrim, AttachContext* ctx, std::vector>&& geos) { + + std::vector> rounded; + rounded.reserve(geos.size()); + + for (const auto& g : geos) { + const auto roundEffect = sksg::RoundEffect::Make(std::move(g)); + rounded.push_back(roundEffect); + + BindProperty(jtrim["r"], &ctx->fAnimators, + [roundEffect](const ScalarValue& r) { + roundEffect->setRadius(r); + }); + } + + return rounded; +} + using GeometryAttacherT = sk_sp (*)(const Json::Value&, AttachContext*); static constexpr GeometryAttacherT gGeometryAttachers[] = { AttachPathGeometry, @@ -475,6 +495,7 @@ using GeometryEffectAttacherT = static constexpr GeometryEffectAttacherT gGeometryEffectAttachers[] = { AttachMergeGeometryEffect, AttachTrimGeometryEffect, + AttachRoundGeometryEffect, }; enum class ShapeType { @@ -500,6 +521,7 @@ const ShapeInfo* FindShapeInfo(const Json::Value& shape) { { "gs", ShapeType::kPaint , 3 }, // gstroke -> AttachGradientStroke { "mm", ShapeType::kGeometryEffect, 0 }, // merge -> AttachMergeGeometryEffect { "rc", ShapeType::kGeometry , 1 }, // rrect -> AttachRRectGeometry + { "rd", ShapeType::kGeometryEffect, 2 }, // round -> AttachRoundGeometryEffect { "sh", ShapeType::kGeometry , 0 }, // shape -> AttachPathGeometry { "sr", ShapeType::kGeometry , 3 }, // polystar -> AttachPolyStarGeometry { "st", ShapeType::kPaint , 1 }, // stroke -> AttachColorStroke diff --git a/experimental/sksg/geometry/SkSGRoundEffect.cpp b/experimental/sksg/geometry/SkSGRoundEffect.cpp new file mode 100644 index 0000000000..8cf9068f65 --- /dev/null +++ b/experimental/sksg/geometry/SkSGRoundEffect.cpp @@ -0,0 +1,56 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkSGRoundEffect.h" + +#include "SkCanvas.h" +#include "SkCornerPathEffect.h" +#include "SkStrokeRec.h" + +namespace sksg { + +RoundEffect::RoundEffect(sk_sp child) + : fChild(std::move(child)) { + this->observeInval(fChild); +} + +RoundEffect::~RoundEffect() { + this->unobserveInval(fChild); +} + +void RoundEffect::onClip(SkCanvas* canvas, bool antiAlias) const { + canvas->clipPath(fRoundedPath, SkClipOp::kIntersect, antiAlias); +} + +void RoundEffect::onDraw(SkCanvas* canvas, const SkPaint& paint) const { + SkASSERT(!paint.getPathEffect()); + + canvas->drawPath(fRoundedPath, paint); +} + +SkPath RoundEffect::onAsPath() const { + return fRoundedPath; +} + +SkRect RoundEffect::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) { + SkASSERT(this->hasInval()); + + const auto childbounds = fChild->revalidate(ic, ctm); + const auto path = fChild->asPath(); + + if (auto round = SkCornerPathEffect::Make(fRadius)) { + fRoundedPath.reset(); + SkStrokeRec rec(SkStrokeRec::kHairline_InitStyle); + SkAssertResult(round->filterPath(&fRoundedPath, path, &rec, &childbounds)); + } else { + fRoundedPath = path; + } + + return fRoundedPath.computeTightBounds(); +} + +} // namespace sksg diff --git a/experimental/sksg/geometry/SkSGRoundEffect.h b/experimental/sksg/geometry/SkSGRoundEffect.h new file mode 100644 index 0000000000..67124ca072 --- /dev/null +++ b/experimental/sksg/geometry/SkSGRoundEffect.h @@ -0,0 +1,50 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkSGRoundEffect_DEFINED +#define SkSGRoundEffect_DEFINED + +#include "SkSGGeometryNode.h" + +#include "SkPath.h" + +namespace sksg { + +/** + * Concrete Geometry node, applying a rounded-corner effect to its child. + */ +class RoundEffect final : public GeometryNode { +public: + static sk_sp Make(sk_sp child) { + return child ? sk_sp(new RoundEffect(std::move(child))) : nullptr; + } + + ~RoundEffect() override; + + SG_ATTRIBUTE(Radius, SkScalar, fRadius) + +protected: + void onClip(SkCanvas*, bool antiAlias) const override; + void onDraw(SkCanvas*, const SkPaint&) const override; + + SkRect onRevalidate(InvalidationController*, const SkMatrix&) override; + SkPath onAsPath() const override; + +private: + explicit RoundEffect(sk_sp); + + const sk_sp fChild; + + SkPath fRoundedPath; + SkScalar fRadius = 0; + + using INHERITED = GeometryNode; +}; + +} // namespace sksg + +#endif // SkSGRoundEffect_DEFINED -- cgit v1.2.3