Skip to content

Commit

Permalink
[svg] Add current node to render context
Browse files Browse the repository at this point in the history
A couple of render-time decisions require knowledge of object bounding
boxes, such as gradients (whose default coordinate space is
"objectBoundingBox". This CL adds the current node being rendered to the
render context so that it can be accessed down-stack (for example, when
gradients are being resolved and added to the paint as Skia shaders).

Each node will overload the bounds computation, for now it just returns
empty bounds for all nodes. TBD if we want to cache bounds somewhere,
either inside the node object or in a separate cache.

Bug: skia:10842
Change-Id: I40061ffedcb840e4dd28dba6351421f5b4fc904b
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/329221
Commit-Queue: Tyler Denniston <tdenniston@google.com>
Reviewed-by: Florin Malita <fmalita@chromium.org>
  • Loading branch information
tdenniston authored and Skia Commit-Bot committed Oct 22, 2020
1 parent 01b05e5 commit 53281c7
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 8 deletions.
6 changes: 6 additions & 0 deletions modules/svg/include/SkSVGNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class SkCanvas;
class SkMatrix;
class SkPaint;
class SkPath;
class SkSVGLengthContext;
class SkSVGRenderContext;
class SkSVGValue;

Expand Down Expand Up @@ -72,6 +73,7 @@ class SkSVGNode : public SkRefCnt {
void render(const SkSVGRenderContext&) const;
bool asPaint(const SkSVGRenderContext&, SkPaint*) const;
SkPath asPath(const SkSVGRenderContext&) const;
SkRect objectBoundingBox(const SkSVGLengthContext&) const;

void setAttribute(SkSVGAttribute, const SkSVGValue&);
bool setAttribute(const char* attributeName, const char* attributeValue);
Expand Down Expand Up @@ -119,6 +121,10 @@ class SkSVGNode : public SkRefCnt {

virtual bool hasChildren() const { return false; }

virtual SkRect onObjectBoundingBox(const SkSVGLengthContext&) const {
return SkRect::MakeEmpty();
}

private:
SkSVGTag fTag;

Expand Down
8 changes: 7 additions & 1 deletion modules/svg/include/SkSVGRenderContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,10 @@ struct SkSVGPresentationContext {
class SkSVGRenderContext {
public:
SkSVGRenderContext(SkCanvas*, const SkSVGIDMapper&, const SkSVGLengthContext&,
const SkSVGPresentationContext&);
const SkSVGPresentationContext&, const SkSVGNode*);
SkSVGRenderContext(const SkSVGRenderContext&);
SkSVGRenderContext(const SkSVGRenderContext&, SkCanvas*);
SkSVGRenderContext(const SkSVGRenderContext&, const SkSVGNode*);
~SkSVGRenderContext();

const SkSVGLengthContext& lengthContext() const { return *fLengthContext; }
Expand Down Expand Up @@ -119,6 +120,9 @@ class SkSVGRenderContext {
// The local computed clip path (not inherited).
const SkPath* clipPath() const { return fClipPath.getMaybeNull(); }

// The node being rendered (may be null).
const SkSVGNode* node() const { return fNode; }

private:
// Stack-only
void* operator new(size_t) = delete;
Expand All @@ -139,6 +143,8 @@ class SkSVGRenderContext {

// clipPath, if present for the current context (not inherited).
SkTLazy<SkPath> fClipPath;

const SkSVGNode* fNode;
};

#endif // SkSVGRenderContext_DEFINED
2 changes: 1 addition & 1 deletion modules/svg/src/SkSVGDOM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,7 @@ void SkSVGDOM::render(SkCanvas* canvas) const {
if (fRoot) {
SkSVGLengthContext lctx(fContainerSize);
SkSVGPresentationContext pctx;
fRoot->render(SkSVGRenderContext(canvas, fIDMapper, lctx, pctx));
fRoot->render(SkSVGRenderContext(canvas, fIDMapper, lctx, pctx, nullptr));
}
}

Expand Down
6 changes: 5 additions & 1 deletion modules/svg/src/SkSVGNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ SkSVGNode::SkSVGNode(SkSVGTag t) : fTag(t) { }
SkSVGNode::~SkSVGNode() { }

void SkSVGNode::render(const SkSVGRenderContext& ctx) const {
SkSVGRenderContext localContext(ctx);
SkSVGRenderContext localContext(ctx, this);

if (this->onPrepareToRender(&localContext)) {
this->onRender(localContext);
Expand Down Expand Up @@ -48,6 +48,10 @@ SkPath SkSVGNode::asPath(const SkSVGRenderContext& ctx) const {
return path;
}

SkRect SkSVGNode::objectBoundingBox(const SkSVGLengthContext& lctx) const {
return this->onObjectBoundingBox(lctx);
}

bool SkSVGNode::onPrepareToRender(SkSVGRenderContext* ctx) const {
ctx->applyPresentationAttributes(fPresentationAttributes,
this->hasChildren() ? 0 : SkSVGRenderContext::kLeaf);
Expand Down
21 changes: 16 additions & 5 deletions modules/svg/src/SkSVGRenderContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ SkSVGPresentationContext::SkSVGPresentationContext()
// Commit initial values to the paint cache.
SkCanvas fakeCanvas(0, 0);
SkSVGRenderContext fake(&fakeCanvas, SkSVGIDMapper(), SkSVGLengthContext(SkSize::Make(0, 0)),
*this);
*this, nullptr);

commitToPaint<SkSVGAttribute::kFill>(fInherited, fake, this);
commitToPaint<SkSVGAttribute::kFillOpacity>(fInherited, fake, this);
Expand All @@ -332,24 +332,35 @@ SkSVGPresentationContext::SkSVGPresentationContext()
SkSVGRenderContext::SkSVGRenderContext(SkCanvas* canvas,
const SkSVGIDMapper& mapper,
const SkSVGLengthContext& lctx,
const SkSVGPresentationContext& pctx)
const SkSVGPresentationContext& pctx,
const SkSVGNode* node)
: fIDMapper(mapper)
, fLengthContext(lctx)
, fPresentationContext(pctx)
, fCanvas(canvas)
, fCanvasSaveCount(canvas->getSaveCount()) {}
, fCanvasSaveCount(canvas->getSaveCount())
, fNode(node) {}

SkSVGRenderContext::SkSVGRenderContext(const SkSVGRenderContext& other)
: SkSVGRenderContext(other.fCanvas,
other.fIDMapper,
*other.fLengthContext,
*other.fPresentationContext) {}
*other.fPresentationContext,
other.fNode) {}

SkSVGRenderContext::SkSVGRenderContext(const SkSVGRenderContext& other, SkCanvas* canvas)
: SkSVGRenderContext(canvas,
other.fIDMapper,
*other.fLengthContext,
*other.fPresentationContext) {}
*other.fPresentationContext,
other.fNode) {}

SkSVGRenderContext::SkSVGRenderContext(const SkSVGRenderContext& other, const SkSVGNode* node)
: SkSVGRenderContext(other.fCanvas,
other.fIDMapper,
*other.fLengthContext,
*other.fPresentationContext,
node) {}

SkSVGRenderContext::~SkSVGRenderContext() {
fCanvas->restoreToCount(fCanvasSaveCount);
Expand Down

0 comments on commit 53281c7

Please sign in to comment.