blob: bfaad0ec06a4684f1779ea74b3e18e069471def2 [file] [log] [blame]
Florin Malita4aa44412017-12-19 12:21:02 -05001/*
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
Florin Malitac0132ff2018-08-09 07:40:01 -040010#include "SkCanvas.h"
11#include "SkPaint.h"
12
Florin Malita4aa44412017-12-19 12:21:02 -050013namespace sksg {
14
Florin Malitac14f1442018-01-05 11:32:31 -050015RenderNode::RenderNode() : INHERITED(0) {}
Florin Malita4aa44412017-12-19 12:21:02 -050016
Florin Malitac0132ff2018-08-09 07:40:01 -040017void RenderNode::render(SkCanvas* canvas, const RenderContext* ctx) const {
Florin Malitac75e2402018-01-03 16:17:29 -050018 SkASSERT(!this->hasInval());
Florin Malitac0132ff2018-08-09 07:40:01 -040019 this->onRender(canvas, ctx);
20}
21
22bool RenderNode::RenderContext::modulatePaint(SkPaint* paint) const {
23 const auto initial_alpha = paint->getAlpha(),
24 alpha = SkToU8(sk_float_round2int(initial_alpha * fOpacity));
25
Florin Malitae1c9d3c2018-08-09 11:19:14 -040026 if (alpha != initial_alpha || fColorFilter) {
Florin Malitac0132ff2018-08-09 07:40:01 -040027 paint->setAlpha(alpha);
Florin Malitae1c9d3c2018-08-09 11:19:14 -040028 paint->setColorFilter(SkColorFilter::MakeComposeFilter(fColorFilter,
29 paint->refColorFilter()));
Florin Malitac0132ff2018-08-09 07:40:01 -040030 return true;
31 }
32
33 return false;
34}
35
36RenderNode::ScopedRenderContext::ScopedRenderContext(SkCanvas* canvas, const RenderContext* ctx)
37 : fCanvas(canvas)
38 , fCtx(ctx)
39 , fRestoreCount(canvas->getSaveCount()) {}
40
41RenderNode::ScopedRenderContext::~ScopedRenderContext() {
42 if (fRestoreCount >= 0) {
43 fCanvas->restoreToCount(fRestoreCount);
44 }
45}
46
47RenderNode::RenderContext* RenderNode::ScopedRenderContext::writableContext() {
48 // If no inherited context is present, allocate one in local storage.
49 if (!fCtx.get()) {
50 // N.B.: we have to force a copy while the default source is in scope.
51 // TODO: add SkTCopyOnWrite::init_copy() to simplify this
52 RenderContext default_ctx;
53 fCtx.init(default_ctx);
54 return fCtx.writable();
55 }
56 return fCtx.writable();
57}
58
59RenderNode::ScopedRenderContext&&
60RenderNode::ScopedRenderContext::modulateOpacity(float opacity) {
61 SkASSERT(opacity >= 0 && opacity <= 1);
62 if (opacity < 1) {
63 this->writableContext()->fOpacity *= opacity;
64 }
65 return std::move(*this);
66}
67
68RenderNode::ScopedRenderContext&&
Florin Malitae1c9d3c2018-08-09 11:19:14 -040069RenderNode::ScopedRenderContext::modulateColorFilter(sk_sp<SkColorFilter> cf) {
70 if (cf) {
71 auto* ctx = this->writableContext();
72 ctx->fColorFilter = SkColorFilter::MakeComposeFilter(std::move(ctx->fColorFilter), cf);
73 }
74 return std::move(*this);
75}
76
77RenderNode::ScopedRenderContext&&
Florin Malitac0132ff2018-08-09 07:40:01 -040078RenderNode::ScopedRenderContext::setIsolation(const SkRect& bounds, bool isolation) {
79 if (isolation && fCtx.get()) {
80 SkPaint layer_paint;
81 if (fCtx->modulatePaint(&layer_paint)) {
82 fCanvas->saveLayer(bounds, &layer_paint);
83 *fCtx.writable() = RenderContext();
84 }
85 }
86 return std::move(*this);
Florin Malita4aa44412017-12-19 12:21:02 -050087}
88
89} // namespace sksg