From 7d529881c4dfc27782c0bced7c7e3a2788975083 Mon Sep 17 00:00:00 2001 From: Florin Malita Date: Thu, 8 Dec 2016 16:04:24 -0500 Subject: [SVGDom] Clipped clipPath support ClipPaths can be clipped too, e.g.: ... Since we're not really drawing clips but resolving their geometry, asPath() needs to take composed clipping into account (and intersect as needed). R=reed@google.com,robertphillips@google.com,stephana@google.com Change-Id: I25959e22fe50f72042147cfe6b416b6b9ac20cd4 Reviewed-on: https://skia-review.googlesource.com/5720 Reviewed-by: Robert Phillips Commit-Queue: Florin Malita --- experimental/svg/model/SkSVGNode.cpp | 14 +++++++++++++- experimental/svg/model/SkSVGRenderContext.cpp | 8 ++++++++ experimental/svg/model/SkSVGRenderContext.h | 7 +++++++ 3 files changed, 28 insertions(+), 1 deletion(-) (limited to 'experimental/svg') diff --git a/experimental/svg/model/SkSVGNode.cpp b/experimental/svg/model/SkSVGNode.cpp index ec452ec9c6..0f3743ffd2 100644 --- a/experimental/svg/model/SkSVGNode.cpp +++ b/experimental/svg/model/SkSVGNode.cpp @@ -7,6 +7,7 @@ #include "SkCanvas.h" #include "SkMatrix.h" +#include "SkPathOps.h" #include "SkSVGNode.h" #include "SkSVGRenderContext.h" #include "SkSVGValue.h" @@ -32,7 +33,18 @@ bool SkSVGNode::asPaint(const SkSVGRenderContext& ctx, SkPaint* paint) const { SkPath SkSVGNode::asPath(const SkSVGRenderContext& ctx) const { SkSVGRenderContext localContext(ctx); - return this->onPrepareToRender(&localContext) ? this->onAsPath(localContext) : SkPath(); + if (!this->onPrepareToRender(&localContext)) { + return SkPath(); + } + + SkPath path = this->onAsPath(localContext); + + if (const auto* clipPath = localContext.clipPath()) { + // There is a clip-path present on the current node. + Op(path, *clipPath, kIntersect_SkPathOp, &path); + } + + return path; } bool SkSVGNode::onPrepareToRender(SkSVGRenderContext* ctx) const { diff --git a/experimental/svg/model/SkSVGRenderContext.cpp b/experimental/svg/model/SkSVGRenderContext.cpp index d8307a05c0..9de605a034 100644 --- a/experimental/svg/model/SkSVGRenderContext.cpp +++ b/experimental/svg/model/SkSVGRenderContext.cpp @@ -328,12 +328,20 @@ void SkSVGRenderContext::applyClip(const SkSVGClip& clip) { const SkPath clipPath = clipNode->asPath(*this); + // We use the computed clip path in two ways: + // + // - apply to the current canvas, for drawing + // - track in the presentation context, for asPath() composition + // + // TODO: the two uses are exclusive, avoid canvas churn when non needed. + // Only save if needed if (fCanvas->getSaveCount() == fCanvasSaveCount) { fCanvas->save(); } fCanvas->clipPath(clipPath, true); + fClipPath.set(clipPath); } const SkPaint* SkSVGRenderContext::fillPaint() const { diff --git a/experimental/svg/model/SkSVGRenderContext.h b/experimental/svg/model/SkSVGRenderContext.h index ab046cd290..3cd38cbd7f 100644 --- a/experimental/svg/model/SkSVGRenderContext.h +++ b/experimental/svg/model/SkSVGRenderContext.h @@ -9,6 +9,7 @@ #define SkSVGRenderContext_DEFINED #include "SkPaint.h" +#include "SkPath.h" #include "SkRect.h" #include "SkSize.h" #include "SkSVGAttribute.h" @@ -79,6 +80,9 @@ public: const SkPaint* fillPaint() const; const SkPaint* strokePaint() const; + // The local computed clip path (not inherited). + const SkPath* clipPath() const { return fClipPath.getMaybeNull(); } + private: // Stack-only void* operator new(size_t) = delete; @@ -95,6 +99,9 @@ private: // The save count on 'fCanvas' at construction time. // A restoreToCount() will be issued on destruction. int fCanvasSaveCount; + + // clipPath, if present for the current context (not inherited). + SkTLazy fClipPath; }; #endif // SkSVGRenderContext_DEFINED -- cgit v1.2.3