• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "modules/sksg/include/SkSGGroup.h"
9 
10 #include "include/core/SkCanvas.h"
11 
12 #include <algorithm>
13 
14 namespace sksg {
15 
Group(std::vector<sk_sp<RenderNode>> children)16 Group::Group(std::vector<sk_sp<RenderNode>> children)
17     : fChildren(std::move(children)) {
18     for (const auto& child : fChildren) {
19         this->observeInval(child);
20     }
21 }
22 
~Group()23 Group::~Group() {
24     for (const auto& child : fChildren) {
25         this->unobserveInval(child);
26     }
27 }
28 
clear()29 void Group::clear() {
30     for (const auto& child : fChildren) {
31         this->unobserveInval(child);
32     }
33     fChildren.clear();
34 }
35 
addChild(sk_sp<RenderNode> node)36 void Group::addChild(sk_sp<RenderNode> node) {
37     // should we allow duplicates?
38     for (const auto& child : fChildren) {
39         if (child == node) {
40             return;
41         }
42     }
43 
44     this->observeInval(node);
45     fChildren.push_back(std::move(node));
46 
47     this->invalidate();
48 }
49 
removeChild(const sk_sp<RenderNode> & node)50 void Group::removeChild(const sk_sp<RenderNode>& node) {
51     SkDEBUGCODE(const auto origSize = fChildren.size());
52     fChildren.erase(std::remove(fChildren.begin(), fChildren.end(), node), fChildren.end());
53     SkASSERT(fChildren.size() == origSize - 1);
54 
55     this->unobserveInval(node);
56     this->invalidate();
57 }
58 
onRender(SkCanvas * canvas,const RenderContext * ctx) const59 void Group::onRender(SkCanvas* canvas, const RenderContext* ctx) const {
60     // TODO: this heuristic works at the moment, but:
61     //   a) it is fragile because it relies on all leaf render nodes being atomic draws
62     //   b) could be improved by e.g. detecting all leaf render draws are non-overlapping
63     const auto isolate = fChildren.size() > 1;
64     const auto local_ctx = ScopedRenderContext(canvas, ctx).setIsolation(this->bounds(),
65                                                                          canvas->getTotalMatrix(),
66                                                                          isolate);
67 
68     for (const auto& child : fChildren) {
69         child->render(canvas, local_ctx);
70     }
71 }
72 
onNodeAt(const SkPoint & p) const73 const RenderNode* Group::onNodeAt(const SkPoint& p) const {
74     for (auto it = fChildren.crbegin(); it != fChildren.crend(); ++it) {
75         if (const auto* node = (*it)->nodeAt(p)) {
76             return node;
77         }
78     }
79 
80     return nullptr;
81 }
82 
onRevalidate(InvalidationController * ic,const SkMatrix & ctm)83 SkRect Group::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
84     SkASSERT(this->hasInval());
85 
86     SkRect bounds = SkRect::MakeEmpty();
87 
88     for (const auto& child : fChildren) {
89         bounds.join(child->revalidate(ic, ctm));
90     }
91 
92     return bounds;
93 }
94 
95 } // namespace sksg
96