[SVGDom] Clipped clipPath support

ClipPaths can be clipped too, e.g.:

  <clipPath id="clip1" clip-path="url(#clip2)">...</clipPath>

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 <robertphillips@google.com>
Commit-Queue: Florin Malita <fmalita@chromium.org>
This commit is contained in:
Florin Malita 2016-12-08 16:04:24 -05:00 committed by Skia Commit-Bot
parent 67702f6322
commit 7d529881c4
3 changed files with 28 additions and 1 deletions

View File

@ -7,6 +7,7 @@
#include "SkCanvas.h" #include "SkCanvas.h"
#include "SkMatrix.h" #include "SkMatrix.h"
#include "SkPathOps.h"
#include "SkSVGNode.h" #include "SkSVGNode.h"
#include "SkSVGRenderContext.h" #include "SkSVGRenderContext.h"
#include "SkSVGValue.h" #include "SkSVGValue.h"
@ -32,7 +33,18 @@ bool SkSVGNode::asPaint(const SkSVGRenderContext& ctx, SkPaint* paint) const {
SkPath SkSVGNode::asPath(const SkSVGRenderContext& ctx) const { SkPath SkSVGNode::asPath(const SkSVGRenderContext& ctx) const {
SkSVGRenderContext localContext(ctx); 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 { bool SkSVGNode::onPrepareToRender(SkSVGRenderContext* ctx) const {

View File

@ -328,12 +328,20 @@ void SkSVGRenderContext::applyClip(const SkSVGClip& clip) {
const SkPath clipPath = clipNode->asPath(*this); 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 // Only save if needed
if (fCanvas->getSaveCount() == fCanvasSaveCount) { if (fCanvas->getSaveCount() == fCanvasSaveCount) {
fCanvas->save(); fCanvas->save();
} }
fCanvas->clipPath(clipPath, true); fCanvas->clipPath(clipPath, true);
fClipPath.set(clipPath);
} }
const SkPaint* SkSVGRenderContext::fillPaint() const { const SkPaint* SkSVGRenderContext::fillPaint() const {

View File

@ -9,6 +9,7 @@
#define SkSVGRenderContext_DEFINED #define SkSVGRenderContext_DEFINED
#include "SkPaint.h" #include "SkPaint.h"
#include "SkPath.h"
#include "SkRect.h" #include "SkRect.h"
#include "SkSize.h" #include "SkSize.h"
#include "SkSVGAttribute.h" #include "SkSVGAttribute.h"
@ -79,6 +80,9 @@ public:
const SkPaint* fillPaint() const; const SkPaint* fillPaint() const;
const SkPaint* strokePaint() const; const SkPaint* strokePaint() const;
// The local computed clip path (not inherited).
const SkPath* clipPath() const { return fClipPath.getMaybeNull(); }
private: private:
// Stack-only // Stack-only
void* operator new(size_t) = delete; void* operator new(size_t) = delete;
@ -95,6 +99,9 @@ private:
// The save count on 'fCanvas' at construction time. // The save count on 'fCanvas' at construction time.
// A restoreToCount() will be issued on destruction. // A restoreToCount() will be issued on destruction.
int fCanvasSaveCount; int fCanvasSaveCount;
// clipPath, if present for the current context (not inherited).
SkTLazy<SkPath> fClipPath;
}; };
#endif // SkSVGRenderContext_DEFINED #endif // SkSVGRenderContext_DEFINED