Home | History | Annotate | Download | only in src
      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