blob: f9e1935515c24f4ee5fe6e81b1cdf9b6e5e29528 [file] [log] [blame]
// 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"
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