diff --git a/experimental/skotty/Skotty.cpp b/experimental/skotty/Skotty.cpp index 7a8e9e35c4..b94cad243b 100644 --- a/experimental/skotty/Skotty.cpp +++ b/experimental/skotty/Skotty.cpp @@ -21,6 +21,7 @@ #include "SkSGInvalidationController.h" #include "SkSGGroup.h" #include "SkSGPath.h" +#include "SkSGRect.h" #include "SkSGTransform.h" #include "SkStream.h" #include "SkTArray.h" @@ -79,7 +80,7 @@ bool AttachProperty(const Json::Value& jprop, AttachContext* ctx, const sk_sp AttachTransform(const Json::Value& t, AttachContext* ctx, sk_sp wrapped_node) { - if (!t.isObject()) + if (!t.isObject() || !wrapped_node) return wrapped_node; auto xform = sk_make_sp(wrapped_node); @@ -143,6 +144,26 @@ sk_sp AttachPathGeometry(const Json::Value& jpath, AttachCon return path_attached ? path_node : nullptr; } +sk_sp AttachRRectGeometry(const Json::Value& jrect, AttachContext* ctx) { + SkASSERT(jrect.isObject()); + + auto rect_node = sksg::RRect::Make(); + auto composite = sk_make_sp(rect_node); + + auto p_attached = AttachProperty(jrect["p"], ctx, composite, + [](const sk_sp& node, const SkPoint& pos) { node->setPosition(pos); }); + auto s_attached = AttachProperty(jrect["s"], ctx, composite, + [](const sk_sp& node, const SkSize& sz) { node->setSize(sz); }); + auto r_attached = AttachProperty(jrect["r"], ctx, composite, + [](const sk_sp& node, SkScalar radius) { node->setRadius(radius); }); + + if (!p_attached && !s_attached && !r_attached) { + return nullptr; + } + + return rect_node; +} + sk_sp AttachColorPaint(const Json::Value& obj, AttachContext* ctx) { SkASSERT(obj.isObject()); @@ -205,6 +226,7 @@ sk_sp AttachStrokePaint(const Json::Value& jstroke, AttachConte using GeometryAttacherT = sk_sp (*)(const Json::Value&, AttachContext*); static constexpr GeometryAttacherT gGeometryAttachers[] = { AttachPathGeometry, + AttachRRectGeometry, }; using PaintAttacherT = sk_sp (*)(const Json::Value&, AttachContext*); @@ -241,6 +263,7 @@ const ShapeInfo* FindShapeInfo(const Json::Value& shape) { static constexpr ShapeInfo gShapeInfo[] = { { "fl", ShapeType::kPaint , 0 }, // fill -> AttachFillPaint { "gr", ShapeType::kGroup , 0 }, // group -> AttachShapeGroup + { "rc", ShapeType::kGeometry , 1 }, // shape -> AttachRRectGeometry { "sh", ShapeType::kGeometry , 0 }, // shape -> AttachPathGeometry { "st", ShapeType::kPaint , 1 }, // stroke -> AttachStrokePaint { "tr", ShapeType::kTransform, 0 }, // transform -> AttachTransform diff --git a/experimental/skotty/SkottyProperties.cpp b/experimental/skotty/SkottyProperties.cpp index 1a3a14593c..7ee4008975 100644 --- a/experimental/skotty/SkottyProperties.cpp +++ b/experimental/skotty/SkottyProperties.cpp @@ -10,6 +10,7 @@ #include "SkColor.h" #include "SkottyPriv.h" #include "SkPath.h" +#include "SkSGRect.h" #include "SkSGTransform.h" namespace skotty { @@ -120,6 +121,24 @@ SkPoint VectorValue::as() const { return SkPoint::Make(x, y); } +template <> +SkSize VectorValue::as() const { + const auto pt = this->as(); + return SkSize::Make(pt.x(), pt.y()); +} + +template <> +std::vector VectorValue::as>() const { + std::vector vec; + vec.reserve(fVals.count()); + + for (const auto& val : fVals) { + vec.push_back(val); + } + + return vec; +} + template <> SkPath ShapeValue::as() const { SkPath path; @@ -146,6 +165,19 @@ SkPath ShapeValue::as() const { return path; } +CompositeRRect::CompositeRRect(sk_sp wrapped_node) + : fRRectNode(std::move(wrapped_node)) {} + +void CompositeRRect::apply() { + // BM "position" == "center position" + auto rr = SkRRect::MakeRectXY(SkRect::MakeXYWH(fPosition.x() - fSize.width() / 2, + fPosition.y() - fSize.height() / 2, + fSize.width(), fSize.height()), + fRadius, + fRadius); + fRRectNode->setRRect(rr); +} + CompositeTransform::CompositeTransform(sk_sp wrapped_node) : fTransformNode(sksg::Transform::Make(std::move(wrapped_node), SkMatrix::I())) {} diff --git a/experimental/skotty/SkottyProperties.h b/experimental/skotty/SkottyProperties.h index 0273aea2f4..e1504747b4 100644 --- a/experimental/skotty/SkottyProperties.h +++ b/experimental/skotty/SkottyProperties.h @@ -20,6 +20,7 @@ class SkPath; namespace sksg { +class RRect; class RenderNode; class Transform; } @@ -100,6 +101,22 @@ struct ShapeValue { p_type f##p_name = p_default; \ public: +class CompositeRRect final : public SkRefCnt { +public: + explicit CompositeRRect(sk_sp); + + COMPOSITE_PROPERTY(Position, SkPoint , SkPoint::Make(0, 0)) + COMPOSITE_PROPERTY(Size , SkSize , SkSize::Make(0, 0)) + COMPOSITE_PROPERTY(Radius , SkScalar, 0) + +private: + void apply(); + + sk_sp fRRectNode; + + using INHERITED = SkRefCnt; +}; + class CompositeTransform final : public SkRefCnt { public: explicit CompositeTransform(sk_sp); diff --git a/experimental/sksg/geometry/SkSGRect.cpp b/experimental/sksg/geometry/SkSGRect.cpp index 69bd94681b..53e6fba400 100644 --- a/experimental/sksg/geometry/SkSGRect.cpp +++ b/experimental/sksg/geometry/SkSGRect.cpp @@ -22,4 +22,14 @@ SkRect Rect::onComputeBounds() const { return fRect; } +RRect::RRect(const SkRRect& rr) : fRRect(rr) {} + +void RRect::onDraw(SkCanvas* canvas, const SkPaint& paint) const { + canvas->drawRRect(fRRect, paint); +} + +SkRect RRect::onComputeBounds() const { + return fRRect.getBounds(); +} + } // namespace sksg diff --git a/experimental/sksg/geometry/SkSGRect.h b/experimental/sksg/geometry/SkSGRect.h index a0e5ec62e8..cc912f0ad0 100644 --- a/experimental/sksg/geometry/SkSGRect.h +++ b/experimental/sksg/geometry/SkSGRect.h @@ -11,6 +11,7 @@ #include "SkSGGeometryNode.h" #include "SkRect.h" +#include "SkRRect.h" class SkCanvas; class SkPaint; @@ -20,7 +21,7 @@ namespace sksg { /** * Concrete Geometry node, wrapping an SkRect. */ -class Rect : public GeometryNode { +class Rect final : public GeometryNode { public: static sk_sp Make() { return sk_sp(new Rect(SkRect::MakeEmpty())); } static sk_sp Make(const SkRect& r) { return sk_sp(new Rect(r)); } @@ -41,6 +42,27 @@ private: SkRect fRect; }; +/** + * Concrete Geometry node, wrapping an SkRRect. + */ +class RRect final : public GeometryNode { +public: + static sk_sp Make() { return sk_sp(new RRect(SkRRect())); } + static sk_sp Make(const SkRRect& rr) { return sk_sp(new RRect(rr)); } + + SG_ATTRIBUTE(RRect, SkRRect, fRRect) + +protected: + void onDraw(SkCanvas*, const SkPaint&) const override; + + SkRect onComputeBounds() const override; + +private: + explicit RRect(const SkRRect&); + + SkRRect fRRect; +}; + } // namespace sksg #endif // SkSGRect_DEFINED