| // Copyright 2019 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "third_party/blink/renderer/platform/geometry/calculation_expression_node.h" |
| |
| #include "base/notreached.h" |
| |
| namespace blink { |
| |
| // ------ CalculationExpressionLeafNode ------ |
| |
| float CalculationExpressionLeafNode::Evaluate(float max_value) const { |
| return value_.pixels + value_.percent / 100 * max_value; |
| } |
| |
| bool CalculationExpressionLeafNode::operator==( |
| const CalculationExpressionNode& other) const { |
| if (!other.IsLeaf()) |
| return false; |
| const auto& other_leaf = To<CalculationExpressionLeafNode>(other); |
| return value_.pixels == other_leaf.value_.pixels && |
| value_.percent == other_leaf.value_.percent; |
| } |
| |
| scoped_refptr<const CalculationExpressionNode> |
| CalculationExpressionLeafNode::Zoom(double factor) const { |
| PixelsAndPercent result(value_.pixels * factor, value_.percent); |
| return base::MakeRefCounted<CalculationExpressionLeafNode>(result); |
| } |
| |
| // ------ CalculationExpressionMultiplicationNode ------ |
| |
| // static |
| scoped_refptr<const CalculationExpressionNode> |
| CalculationExpressionMultiplicationNode::CreateSimplified( |
| scoped_refptr<const CalculationExpressionNode> node, |
| float factor) { |
| if (!node->IsLeaf()) { |
| return base::MakeRefCounted<CalculationExpressionMultiplicationNode>( |
| std::move(node), factor); |
| } |
| const auto& leaf = To<CalculationExpressionLeafNode>(*node); |
| PixelsAndPercent value(leaf.Pixels() * factor, leaf.Percent() * factor); |
| return base::MakeRefCounted<CalculationExpressionLeafNode>(value); |
| } |
| |
| float CalculationExpressionMultiplicationNode::Evaluate(float max_value) const { |
| return child_->Evaluate(max_value) * factor_; |
| } |
| |
| bool CalculationExpressionMultiplicationNode::operator==( |
| const CalculationExpressionNode& other) const { |
| if (!other.IsMultiplication()) |
| return false; |
| const auto& other_multiply = |
| To<CalculationExpressionMultiplicationNode>(other); |
| return factor_ == other_multiply.factor_ && *child_ == *other_multiply.child_; |
| } |
| |
| scoped_refptr<const CalculationExpressionNode> |
| CalculationExpressionMultiplicationNode::Zoom(double factor) const { |
| return CreateSimplified(child_->Zoom(factor), factor_); |
| } |
| |
| // ------ CalculationExpressionAdditiveNode ------ |
| |
| // static |
| scoped_refptr<const CalculationExpressionNode> |
| CalculationExpressionAdditiveNode::CreateSimplified( |
| scoped_refptr<const CalculationExpressionNode> lhs, |
| scoped_refptr<const CalculationExpressionNode> rhs, |
| Type type) { |
| if (!lhs->IsLeaf() || !rhs->IsLeaf()) { |
| return base::MakeRefCounted<CalculationExpressionAdditiveNode>( |
| std::move(lhs), std::move(rhs), type); |
| } |
| const auto& left_leaf = To<CalculationExpressionLeafNode>(*lhs); |
| const auto& right_leaf = To<CalculationExpressionLeafNode>(*rhs); |
| PixelsAndPercent value = left_leaf.GetPixelsAndPercent(); |
| if (type == Type::kAdd) { |
| value.pixels += right_leaf.Pixels(); |
| value.percent += right_leaf.Percent(); |
| } else { |
| value.pixels -= right_leaf.Pixels(); |
| value.percent -= right_leaf.Percent(); |
| } |
| return base::MakeRefCounted<CalculationExpressionLeafNode>(value); |
| } |
| |
| float CalculationExpressionAdditiveNode::Evaluate(float max_value) const { |
| if (IsAdd()) |
| return lhs_->Evaluate(max_value) + rhs_->Evaluate(max_value); |
| if (IsSubtract()) |
| return lhs_->Evaluate(max_value) - rhs_->Evaluate(max_value); |
| NOTREACHED(); |
| return 0; |
| } |
| |
| bool CalculationExpressionAdditiveNode::operator==( |
| const CalculationExpressionNode& other) const { |
| if (!other.IsAdditive()) |
| return false; |
| const auto& other_add_subtract = To<CalculationExpressionAdditiveNode>(other); |
| // Do we need to consider add as commutative? |
| return type_ == other_add_subtract.type_ && |
| *lhs_ == *other_add_subtract.lhs_ && *rhs_ == *other_add_subtract.rhs_; |
| } |
| |
| scoped_refptr<const CalculationExpressionNode> |
| CalculationExpressionAdditiveNode::Zoom(double factor) const { |
| return CreateSimplified(lhs_->Zoom(factor), rhs_->Zoom(factor), type_); |
| } |
| |
| // ------ CalculationExpressionComparisonNode ------ |
| |
| // static |
| scoped_refptr<const CalculationExpressionNode> |
| CalculationExpressionComparisonNode::CreateSimplified( |
| Vector<scoped_refptr<const CalculationExpressionNode>>&& operands, |
| Type type) { |
| DCHECK(operands.size()); |
| float simplified_px; |
| bool can_simplify = true; |
| for (wtf_size_t i = 0; i < operands.size(); ++i) { |
| const auto* leaf = DynamicTo<CalculationExpressionLeafNode>(*operands[i]); |
| if (!leaf || leaf->Percent()) { |
| can_simplify = false; |
| break; |
| } |
| if (!i) { |
| simplified_px = leaf->Pixels(); |
| } else { |
| if (type == Type::kMin) |
| simplified_px = std::min(simplified_px, leaf->Pixels()); |
| else |
| simplified_px = std::max(simplified_px, leaf->Pixels()); |
| } |
| } |
| if (can_simplify) { |
| return base::MakeRefCounted<CalculationExpressionLeafNode>( |
| PixelsAndPercent(simplified_px, 0)); |
| } |
| return base::MakeRefCounted<CalculationExpressionComparisonNode>( |
| std::move(operands), type); |
| } |
| |
| float CalculationExpressionComparisonNode::Evaluate(float max_value) const { |
| float result = operands_.front()->Evaluate(max_value); |
| if (IsMin()) { |
| for (wtf_size_t i = 1; i < operands_.size(); ++i) |
| result = std::min(result, operands_[i]->Evaluate(max_value)); |
| } else if (IsMax()) { |
| for (wtf_size_t i = 1; i < operands_.size(); ++i) |
| result = std::max(result, operands_[i]->Evaluate(max_value)); |
| } else { |
| NOTREACHED(); |
| } |
| return result; |
| } |
| |
| bool CalculationExpressionComparisonNode::operator==( |
| const CalculationExpressionNode& other) const { |
| if (!other.IsComparison()) |
| return false; |
| const auto& other_comparison = To<CalculationExpressionComparisonNode>(other); |
| if (type_ != other_comparison.type_) |
| return false; |
| if (operands_.size() != other_comparison.operands_.size()) |
| return false; |
| // We may consider ignoring operand ordering to allow better memory |
| // optimization. The code complexity might not pay off, though. |
| for (wtf_size_t i = 0; i < operands_.size(); ++i) { |
| if (*operands_[i] != *other_comparison.operands_[i]) |
| return false; |
| } |
| return true; |
| } |
| |
| scoped_refptr<const CalculationExpressionNode> |
| CalculationExpressionComparisonNode::Zoom(double factor) const { |
| Vector<scoped_refptr<const CalculationExpressionNode>> cloned_operands; |
| cloned_operands.ReserveCapacity(operands_.size()); |
| for (const auto& operand : operands_) |
| cloned_operands.push_back(operand->Zoom(factor)); |
| return CreateSimplified(std::move(cloned_operands), type_); |
| } |
| |
| } // namespace blink |