1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2017 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "modules/sksg/include/SkSGGroup.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h" 11cb93a386Sopenharmony_ci 12cb93a386Sopenharmony_ci#include <algorithm> 13cb93a386Sopenharmony_ci 14cb93a386Sopenharmony_cinamespace sksg { 15cb93a386Sopenharmony_ci 16cb93a386Sopenharmony_ciGroup::Group() = default; 17cb93a386Sopenharmony_ci 18cb93a386Sopenharmony_ciGroup::Group(std::vector<sk_sp<RenderNode>> children) 19cb93a386Sopenharmony_ci : fChildren(std::move(children)) { 20cb93a386Sopenharmony_ci for (const auto& child : fChildren) { 21cb93a386Sopenharmony_ci this->observeInval(child); 22cb93a386Sopenharmony_ci } 23cb93a386Sopenharmony_ci} 24cb93a386Sopenharmony_ci 25cb93a386Sopenharmony_ciGroup::~Group() { 26cb93a386Sopenharmony_ci for (const auto& child : fChildren) { 27cb93a386Sopenharmony_ci this->unobserveInval(child); 28cb93a386Sopenharmony_ci } 29cb93a386Sopenharmony_ci} 30cb93a386Sopenharmony_ci 31cb93a386Sopenharmony_civoid Group::clear() { 32cb93a386Sopenharmony_ci for (const auto& child : fChildren) { 33cb93a386Sopenharmony_ci this->unobserveInval(child); 34cb93a386Sopenharmony_ci } 35cb93a386Sopenharmony_ci fChildren.clear(); 36cb93a386Sopenharmony_ci} 37cb93a386Sopenharmony_ci 38cb93a386Sopenharmony_civoid Group::addChild(sk_sp<RenderNode> node) { 39cb93a386Sopenharmony_ci // should we allow duplicates? 40cb93a386Sopenharmony_ci for (const auto& child : fChildren) { 41cb93a386Sopenharmony_ci if (child == node) { 42cb93a386Sopenharmony_ci return; 43cb93a386Sopenharmony_ci } 44cb93a386Sopenharmony_ci } 45cb93a386Sopenharmony_ci 46cb93a386Sopenharmony_ci this->observeInval(node); 47cb93a386Sopenharmony_ci fChildren.push_back(std::move(node)); 48cb93a386Sopenharmony_ci 49cb93a386Sopenharmony_ci this->invalidate(); 50cb93a386Sopenharmony_ci} 51cb93a386Sopenharmony_ci 52cb93a386Sopenharmony_civoid Group::removeChild(const sk_sp<RenderNode>& node) { 53cb93a386Sopenharmony_ci SkDEBUGCODE(const auto origSize = fChildren.size()); 54cb93a386Sopenharmony_ci fChildren.erase(std::remove(fChildren.begin(), fChildren.end(), node), fChildren.end()); 55cb93a386Sopenharmony_ci SkASSERT(fChildren.size() == origSize - 1); 56cb93a386Sopenharmony_ci 57cb93a386Sopenharmony_ci this->unobserveInval(node); 58cb93a386Sopenharmony_ci this->invalidate(); 59cb93a386Sopenharmony_ci} 60cb93a386Sopenharmony_ci 61cb93a386Sopenharmony_civoid Group::onRender(SkCanvas* canvas, const RenderContext* ctx) const { 62cb93a386Sopenharmony_ci const auto local_ctx = ScopedRenderContext(canvas, ctx).setIsolation(this->bounds(), 63cb93a386Sopenharmony_ci canvas->getTotalMatrix(), 64cb93a386Sopenharmony_ci fRequiresIsolation); 65cb93a386Sopenharmony_ci 66cb93a386Sopenharmony_ci for (const auto& child : fChildren) { 67cb93a386Sopenharmony_ci child->render(canvas, local_ctx); 68cb93a386Sopenharmony_ci } 69cb93a386Sopenharmony_ci} 70cb93a386Sopenharmony_ci 71cb93a386Sopenharmony_ciconst RenderNode* Group::onNodeAt(const SkPoint& p) const { 72cb93a386Sopenharmony_ci for (auto it = fChildren.crbegin(); it != fChildren.crend(); ++it) { 73cb93a386Sopenharmony_ci if (const auto* node = (*it)->nodeAt(p)) { 74cb93a386Sopenharmony_ci return node; 75cb93a386Sopenharmony_ci } 76cb93a386Sopenharmony_ci } 77cb93a386Sopenharmony_ci 78cb93a386Sopenharmony_ci return nullptr; 79cb93a386Sopenharmony_ci} 80cb93a386Sopenharmony_ci 81cb93a386Sopenharmony_ciSkRect Group::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) { 82cb93a386Sopenharmony_ci SkASSERT(this->hasInval()); 83cb93a386Sopenharmony_ci 84cb93a386Sopenharmony_ci SkRect bounds = SkRect::MakeEmpty(); 85cb93a386Sopenharmony_ci fRequiresIsolation = false; 86cb93a386Sopenharmony_ci 87cb93a386Sopenharmony_ci for (size_t i = 0; i < fChildren.size(); ++i) { 88cb93a386Sopenharmony_ci const auto child_bounds = fChildren[i]->revalidate(ic, ctm); 89cb93a386Sopenharmony_ci 90cb93a386Sopenharmony_ci // If any of the child nodes overlap, group effects require layer isolation. 91cb93a386Sopenharmony_ci if (!fRequiresIsolation && i > 0 && child_bounds.intersects(bounds)) { 92cb93a386Sopenharmony_ci#if 1 93cb93a386Sopenharmony_ci // Testing conservatively against the union of prev bounds is cheap and good enough. 94cb93a386Sopenharmony_ci fRequiresIsolation = true; 95cb93a386Sopenharmony_ci#else 96cb93a386Sopenharmony_ci // Testing exhaustively doesn't seem to increase the layer elision rate in practice. 97cb93a386Sopenharmony_ci for (size_t j = 0; j < i; ++ j) { 98cb93a386Sopenharmony_ci if (child_bounds.intersects(fChildren[i]->bounds())) { 99cb93a386Sopenharmony_ci fRequiresIsolation = true; 100cb93a386Sopenharmony_ci break; 101cb93a386Sopenharmony_ci } 102cb93a386Sopenharmony_ci } 103cb93a386Sopenharmony_ci#endif 104cb93a386Sopenharmony_ci } 105cb93a386Sopenharmony_ci 106cb93a386Sopenharmony_ci bounds.join(child_bounds); 107cb93a386Sopenharmony_ci } 108cb93a386Sopenharmony_ci 109cb93a386Sopenharmony_ci return bounds; 110cb93a386Sopenharmony_ci} 111cb93a386Sopenharmony_ci 112cb93a386Sopenharmony_ci} // namespace sksg 113