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 "SkSGGroup.h"
9
10 #include <algorithm>
11
12 namespace sksg {
13
Group(std::vector<sk_sp<RenderNode>> children)14 Group::Group(std::vector<sk_sp<RenderNode>> children)
15 : fChildren(std::move(children)) {
16 for (const auto& child : fChildren) {
17 this->observeInval(child);
18 }
19 }
20
~Group()21 Group::~Group() {
22 for (const auto& child : fChildren) {
23 this->unobserveInval(child);
24 }
25 }
26
clear()27 void Group::clear() {
28 for (const auto& child : fChildren) {
29 this->unobserveInval(child);
30 }
31 fChildren.clear();
32 }
33
addChild(sk_sp<RenderNode> node)34 void 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
42 this->observeInval(node);
43 fChildren.push_back(std::move(node));
44
45 this->invalidate();
46 }
47
removeChild(const sk_sp<RenderNode> & node)48 void Group::removeChild(const sk_sp<RenderNode>& node) {
49 SkDEBUGCODE(const auto origSize = fChildren.size());
50 fChildren.erase(std::remove(fChildren.begin(), fChildren.end(), node), fChildren.end());
51 SkASSERT(fChildren.size() == origSize - 1);
52
53 this->unobserveInval(node);
54 this->invalidate();
55 }
56
onRender(SkCanvas * canvas,const RenderContext * ctx) const57 void 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
61 const auto isolate = fChildren.size() > 1;
62 const auto local_ctx = ScopedRenderContext(canvas, ctx).setIsolation(this->bounds(), isolate);
63
64 for (const auto& child : fChildren) {
65 child->render(canvas, local_ctx);
66 }
67 }
68
onNodeAt(const SkPoint & p) const69 const RenderNode* Group::onNodeAt(const SkPoint& p) const {
70 for (auto it = fChildren.crbegin(); it != fChildren.crend(); ++it) {
71 if (const auto* node = (*it)->nodeAt(p)) {
72 return node;
73 }
74 }
75
76 return nullptr;
77 }
78
onRevalidate(InvalidationController * ic,const SkMatrix & ctm)79 SkRect Group::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
80 SkASSERT(this->hasInval());
81
82 SkRect bounds = SkRect::MakeEmpty();
83
84 for (const auto& child : fChildren) {
85 bounds.join(child->revalidate(ic, ctm));
86 }
87
88 return bounds;
89 }
90
91 } // namespace sksg
92