blob: 3c1a6cfa3afd12313b9ef679fdf452659ec5da62 [file] [log] [blame]
// Copyright 2017 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cobalt/renderer/rasterizer/common/find_node.h"
#include "base/optional.h"
#include "cobalt/base/polymorphic_downcast.h"
#include "cobalt/render_tree/animations/animate_node.h"
namespace cobalt {
namespace renderer {
namespace rasterizer {
namespace common {
class FinderNodeVisitor : public render_tree::NodeVisitor {
public:
FinderNodeVisitor(NodeFilterFunction<render_tree::Node> filter_function,
base::Optional<NodeReplaceFunction> replace_function)
: filter_function_(filter_function),
replace_function_(replace_function) {}
void Visit(render_tree::animations::AnimateNode* animate) override {
VisitNode(animate);
}
void Visit(render_tree::ClearRectNode* clear_rect_node) override {
VisitNode(clear_rect_node);
}
void Visit(render_tree::CompositionNode* composition_node) override {
VisitNode(composition_node);
}
void Visit(render_tree::FilterNode* filter_node) override {
VisitNode(filter_node);
}
void Visit(render_tree::ImageNode* image_node) override {
VisitNode(image_node);
}
void Visit(render_tree::MatrixTransform3DNode* transform_3d_node) override {
VisitNode(transform_3d_node);
}
void Visit(render_tree::MatrixTransformNode* transform_node) override {
VisitNode(transform_node);
}
void Visit(render_tree::PunchThroughVideoNode* punch_through) override {
VisitNode(punch_through);
}
void Visit(render_tree::RectNode* rect) override { VisitNode(rect); }
void Visit(render_tree::RectShadowNode* rect) override { VisitNode(rect); }
void Visit(render_tree::TextNode* text) override { VisitNode(text); }
virtual ~FinderNodeVisitor() {}
scoped_refptr<render_tree::Node> GetFoundNode() const { return found_node_; }
scoped_refptr<render_tree::Node> GetReplaceWithNode() {
return replace_with_;
}
private:
template <typename T>
void VisitNode(T* node) {
if (filter_function_.Run(static_cast<render_tree::Node*>(node))) {
found_node_ = node;
if (replace_function_) {
replace_with_ = replace_function_->Run(node);
}
} else {
VisitNodeChildren(node);
}
}
template <typename T>
typename base::enable_if<!render_tree::ChildIterator<T>::has_children>::type
VisitNodeChildren(T* node) {
// No children to visit.
}
template <typename T>
typename base::enable_if<render_tree::ChildIterator<T>::has_children>::type
VisitNodeChildren(T* node) {
render_tree::ChildIterator<T> child_iterator(node);
while (render_tree::Node* child = child_iterator.GetCurrent()) {
child->Accept(this);
if (found_node_) {
if (replace_with_) {
child_iterator.ReplaceCurrent(replace_with_);
}
break;
}
child_iterator.Next();
}
if (replace_with_) {
replace_with_ = new T(child_iterator.TakeReplacedChildrenBuilder());
}
}
NodeFilterFunction<render_tree::Node> filter_function_;
base::Optional<NodeReplaceFunction> replace_function_;
scoped_refptr<render_tree::Node> found_node_;
scoped_refptr<render_tree::Node> replace_with_;
};
template <>
NodeSearchResult<render_tree::Node> FindNode<render_tree::Node>(
const scoped_refptr<render_tree::Node>& tree,
NodeFilterFunction<render_tree::Node> filter_function,
base::Optional<NodeReplaceFunction> replace_function) {
FinderNodeVisitor visitor(filter_function, replace_function);
tree->Accept(&visitor);
NodeSearchResult<render_tree::Node> result;
result.found_node = visitor.GetFoundNode();
result.replaced_tree = visitor.GetReplaceWithNode();
if (result.replaced_tree.get() == NULL) {
result.replaced_tree = tree;
}
return result;
}
bool HasMapToMesh(render_tree::FilterNode* filter_node) {
return static_cast<bool>(filter_node->data().map_to_mesh_filter);
}
render_tree::Node* ReplaceWithEmptyCompositionNode(
render_tree::Node* filter_node) {
return new render_tree::CompositionNode(
render_tree::CompositionNode::Builder());
}
} // namespace common
} // namespace rasterizer
} // namespace renderer
} // namespace cobalt