| // Copyright 2017 Google Inc. 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::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 == 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 |