| /* |
| * Copyright 2017 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #ifndef SkSGRenderNode_DEFINED |
| #define SkSGRenderNode_DEFINED |
| |
| #include "SkSGNode.h" |
| |
| #include "SkColorFilter.h" |
| |
| class SkCanvas; |
| class SkImageFilter; |
| class SkPaint; |
| |
| namespace sksg { |
| |
| /** |
| * Base class for nodes which can render to a canvas. |
| */ |
| class RenderNode : public Node { |
| protected: |
| struct RenderContext; |
| |
| public: |
| // Render the node and its descendants to the canvas. |
| void render(SkCanvas*, const RenderContext* = nullptr) const; |
| |
| // Perform a front-to-back hit-test, and return the RenderNode located at |point|. |
| // Normally, hit-testing stops at leaf Draw nodes. |
| const RenderNode* nodeAt(const SkPoint& point) const; |
| |
| protected: |
| explicit RenderNode(uint32_t inval_traits = 0); |
| |
| virtual void onRender(SkCanvas*, const RenderContext*) const = 0; |
| virtual const RenderNode* onNodeAt(const SkPoint& p) const = 0; |
| |
| // Paint property overrides. |
| // These are deferred until we can determine whether they can be applied to the individual |
| // draw paints, or whether they require content isolation (applied to a layer). |
| struct RenderContext { |
| sk_sp<SkColorFilter> fColorFilter; |
| float fOpacity = 1; |
| |
| // Returns true if the paint was modified. |
| bool modulatePaint(SkPaint*) const; |
| }; |
| |
| class ScopedRenderContext final { |
| public: |
| ScopedRenderContext(SkCanvas*, const RenderContext*); |
| ~ScopedRenderContext(); |
| |
| ScopedRenderContext(ScopedRenderContext&& that) { *this = std::move(that); } |
| |
| ScopedRenderContext& operator=(ScopedRenderContext&& that) { |
| fCanvas = that.fCanvas; |
| fCtx = std::move(that.fCtx); |
| fRestoreCount = that.fRestoreCount; |
| |
| // scope ownership is being transferred |
| that.fRestoreCount = -1; |
| |
| return *this; |
| } |
| |
| operator const RenderContext* () const { return &fCtx; } |
| |
| // Add (cumulative) paint overrides to a render node sub-DAG. |
| ScopedRenderContext&& modulateOpacity(float opacity); |
| ScopedRenderContext&& modulateColorFilter(sk_sp<SkColorFilter>); |
| |
| // Force content isolation for a node sub-DAG by applying the RenderContext |
| // overrides via a layer. |
| ScopedRenderContext&& setIsolation(const SkRect& bounds, bool do_isolate); |
| |
| // Similarly, force content isolation by applying the RenderContext overrides and |
| // an image filter via a single layer. |
| ScopedRenderContext&& setFilterIsolation(const SkRect& bounds, sk_sp<SkImageFilter>); |
| |
| private: |
| // stack-only |
| void* operator new(size_t) = delete; |
| void* operator new(size_t, void*) = delete; |
| |
| // Scopes cannot be copied. |
| ScopedRenderContext(const ScopedRenderContext&) = delete; |
| ScopedRenderContext& operator=(const ScopedRenderContext&) = delete; |
| |
| SkCanvas* fCanvas; |
| RenderContext fCtx; |
| int fRestoreCount; |
| }; |
| |
| private: |
| friend class ImageFilterEffect; |
| |
| typedef Node INHERITED; |
| }; |
| |
| } // namespace sksg |
| |
| #endif // SkSGRenderNode_DEFINED |