1 /*
2 * Copyright 2017 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "SkSGRenderNode.h"
9
10 #include "SkCanvas.h"
11 #include "SkImageFilter.h"
12 #include "SkPaint.h"
13
14 namespace sksg {
15
RenderNode(uint32_t inval_traits)16 RenderNode::RenderNode(uint32_t inval_traits) : INHERITED(inval_traits) {}
17
render(SkCanvas * canvas,const RenderContext * ctx) const18 void RenderNode::render(SkCanvas* canvas, const RenderContext* ctx) const {
19 SkASSERT(!this->hasInval());
20 if (!this->bounds().isEmpty()) {
21 this->onRender(canvas, ctx);
22 }
23 }
24
nodeAt(const SkPoint & p) const25 const RenderNode* RenderNode::nodeAt(const SkPoint& p) const {
26 return this->bounds().contains(p.x(), p.y()) ? this->onNodeAt(p) : nullptr;
27 }
28
modulatePaint(SkPaint * paint) const29 bool RenderNode::RenderContext::modulatePaint(SkPaint* paint) const {
30 const auto initial_alpha = paint->getAlpha(),
31 alpha = SkToU8(sk_float_round2int(initial_alpha * fOpacity));
32
33 if (alpha != initial_alpha || fColorFilter || fBlendMode != paint->getBlendMode()) {
34 paint->setAlpha(alpha);
35 paint->setColorFilter(SkColorFilter::MakeComposeFilter(fColorFilter,
36 paint->refColorFilter()));
37 paint->setBlendMode(fBlendMode);
38 return true;
39 }
40
41 return false;
42 }
43
ScopedRenderContext(SkCanvas * canvas,const RenderContext * ctx)44 RenderNode::ScopedRenderContext::ScopedRenderContext(SkCanvas* canvas, const RenderContext* ctx)
45 : fCanvas(canvas)
46 , fCtx(ctx ? *ctx : RenderContext())
47 , fRestoreCount(canvas->getSaveCount()) {}
48
~ScopedRenderContext()49 RenderNode::ScopedRenderContext::~ScopedRenderContext() {
50 if (fRestoreCount >= 0) {
51 fCanvas->restoreToCount(fRestoreCount);
52 }
53 }
54
55 RenderNode::ScopedRenderContext&&
modulateOpacity(float opacity)56 RenderNode::ScopedRenderContext::modulateOpacity(float opacity) {
57 SkASSERT(opacity >= 0 && opacity <= 1);
58 fCtx.fOpacity *= opacity;
59 return std::move(*this);
60 }
61
62 RenderNode::ScopedRenderContext&&
modulateColorFilter(sk_sp<SkColorFilter> cf)63 RenderNode::ScopedRenderContext::modulateColorFilter(sk_sp<SkColorFilter> cf) {
64 fCtx.fColorFilter = SkColorFilter::MakeComposeFilter(std::move(fCtx.fColorFilter),
65 std::move(cf));
66 return std::move(*this);
67 }
68
69 RenderNode::ScopedRenderContext&&
modulateBlendMode(SkBlendMode mode)70 RenderNode::ScopedRenderContext::modulateBlendMode(SkBlendMode mode) {
71 fCtx.fBlendMode = mode;
72 return std::move(*this);
73 }
74
75 RenderNode::ScopedRenderContext&&
setIsolation(const SkRect & bounds,bool isolation)76 RenderNode::ScopedRenderContext::setIsolation(const SkRect& bounds, bool isolation) {
77 if (isolation) {
78 SkPaint layer_paint;
79 if (fCtx.modulatePaint(&layer_paint)) {
80 fCanvas->saveLayer(bounds, &layer_paint);
81 fCtx = RenderContext();
82 }
83 }
84 return std::move(*this);
85 }
86
87 RenderNode::ScopedRenderContext&&
setFilterIsolation(const SkRect & bounds,sk_sp<SkImageFilter> filter)88 RenderNode::ScopedRenderContext::setFilterIsolation(const SkRect& bounds,
89 sk_sp<SkImageFilter> filter) {
90 SkPaint layer_paint;
91 fCtx.modulatePaint(&layer_paint);
92
93 SkASSERT(!layer_paint.getImageFilter());
94 layer_paint.setImageFilter(std::move(filter));
95 fCanvas->saveLayer(bounds, &layer_paint);
96 fCtx = RenderContext();
97
98 return std::move(*this);
99 }
100
101 } // namespace sksg
102