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 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 21 Group::~Group() { 22 for (const auto& child : fChildren) { 23 this->unobserveInval(child); 24 } 25 } 26 27 void Group::clear() { 28 for (const auto& child : fChildren) { 29 this->unobserveInval(child); 30 } 31 fChildren.clear(); 32 } 33 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 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 57 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 69 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 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