blob: cc44b31c33a2bedd5dd8ce25ccacbf2f51b0f115 [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 "SkSGGroup.h"
9
Florin Malitaca858b62018-09-02 13:44:13 -040010#include <algorithm>
11
Florin Malita4aa44412017-12-19 12:21:02 -050012namespace sksg {
13
Florin Malitacd9d0742018-09-10 09:57:15 -040014Group::Group(std::vector<sk_sp<RenderNode>> children)
15 : fChildren(std::move(children)) {
16 for (const auto& child : fChildren) {
17 this->observeInval(child);
18 }
19}
Florin Malita4aa44412017-12-19 12:21:02 -050020
21Group::~Group() {
22 for (const auto& child : fChildren) {
Florin Malita3ba3fa72018-01-22 10:19:28 -050023 this->unobserveInval(child);
Florin Malita4aa44412017-12-19 12:21:02 -050024 }
25}
26
Florin Malita8ec9a602019-02-01 17:59:25 -050027void Group::clear() {
28 for (const auto& child : fChildren) {
29 this->unobserveInval(child);
30 }
31 fChildren.clear();
32}
33
Florin Malita4aa44412017-12-19 12:21:02 -050034void Group::addChild(sk_sp<RenderNode> node) {
35 // should we allow duplicates?
36 for (const auto& child : fChildren) {
37 if (child == node) {
38 return;
39 }
40 }
41
Florin Malita3ba3fa72018-01-22 10:19:28 -050042 this->observeInval(node);
Florin Malita4aa44412017-12-19 12:21:02 -050043 fChildren.push_back(std::move(node));
Florin Malitac75e2402018-01-03 16:17:29 -050044
Florin Malitac14f1442018-01-05 11:32:31 -050045 this->invalidate();
Florin Malita4aa44412017-12-19 12:21:02 -050046}
47
48void Group::removeChild(const sk_sp<RenderNode>& node) {
Florin Malitaca858b62018-09-02 13:44:13 -040049 SkDEBUGCODE(const auto origSize = fChildren.size());
50 fChildren.erase(std::remove(fChildren.begin(), fChildren.end(), node), fChildren.end());
51 SkASSERT(fChildren.size() == origSize - 1);
Florin Malitac75e2402018-01-03 16:17:29 -050052
Florin Malitabee88d42018-10-02 13:05:39 -040053 this->unobserveInval(node);
Florin Malitac14f1442018-01-05 11:32:31 -050054 this->invalidate();
Florin Malita4aa44412017-12-19 12:21:02 -050055}
56
Florin Malitac0132ff2018-08-09 07:40:01 -040057void Group::onRender(SkCanvas* canvas, const RenderContext* ctx) const {
58 // TODO: this heuristic works at the moment, but:
59 // a) it is fragile because it relies on all leaf render nodes being atomic draws
60 // b) could be improved by e.g. detecting all leaf render draws are non-overlapping
Florin Malitaca858b62018-09-02 13:44:13 -040061 const auto isolate = fChildren.size() > 1;
Florin Malitac0132ff2018-08-09 07:40:01 -040062 const auto local_ctx = ScopedRenderContext(canvas, ctx).setIsolation(this->bounds(), isolate);
63
Florin Malita4aa44412017-12-19 12:21:02 -050064 for (const auto& child : fChildren) {
Florin Malitac0132ff2018-08-09 07:40:01 -040065 child->render(canvas, local_ctx);
Florin Malita4aa44412017-12-19 12:21:02 -050066 }
67}
68
Florin Malitaeb46bd82019-02-12 09:33:21 -050069const RenderNode* Group::onNodeAt(const SkPoint& p) const {
70 for (const auto& child : fChildren) {
71 if (const auto* node = child->nodeAt(p)) {
72 return node;
73 }
74 }
75
76 return nullptr;
77}
78
Florin Malitac14f1442018-01-05 11:32:31 -050079SkRect Group::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
Florin Malitac75e2402018-01-03 16:17:29 -050080 SkASSERT(this->hasInval());
81
Florin Malitac14f1442018-01-05 11:32:31 -050082 SkRect bounds = SkRect::MakeEmpty();
Florin Malitac75e2402018-01-03 16:17:29 -050083
Florin Malita4aa44412017-12-19 12:21:02 -050084 for (const auto& child : fChildren) {
Florin Malitac14f1442018-01-05 11:32:31 -050085 bounds.join(child->revalidate(ic, ctm));
Florin Malita4aa44412017-12-19 12:21:02 -050086 }
Florin Malitac75e2402018-01-03 16:17:29 -050087
Florin Malitac14f1442018-01-05 11:32:31 -050088 return bounds;
Florin Malita4aa44412017-12-19 12:21:02 -050089}
90
91} // namespace sksg