1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "third_party/blink/renderer/platform/geometry/calculation_expression_node.h"
6
7 #include "base/notreached.h"
8
9 namespace blink {
10
11 // ------ CalculationExpressionLeafNode ------
12
Evaluate(float max_value) const13 float CalculationExpressionLeafNode::Evaluate(float max_value) const {
14 return value_.pixels + value_.percent / 100 * max_value;
15 }
16
operator ==(const CalculationExpressionNode & other) const17 bool CalculationExpressionLeafNode::operator==(
18 const CalculationExpressionNode& other) const {
19 if (!other.IsLeaf())
20 return false;
21 const auto& other_leaf = To<CalculationExpressionLeafNode>(other);
22 return value_.pixels == other_leaf.value_.pixels &&
23 value_.percent == other_leaf.value_.percent;
24 }
25
26 scoped_refptr<const CalculationExpressionNode>
Zoom(double factor) const27 CalculationExpressionLeafNode::Zoom(double factor) const {
28 PixelsAndPercent result(value_.pixels * factor, value_.percent);
29 return base::MakeRefCounted<CalculationExpressionLeafNode>(result);
30 }
31
32 // ------ CalculationExpressionMultiplicationNode ------
33
34 // static
35 scoped_refptr<const CalculationExpressionNode>
CreateSimplified(scoped_refptr<const CalculationExpressionNode> node,float factor)36 CalculationExpressionMultiplicationNode::CreateSimplified(
37 scoped_refptr<const CalculationExpressionNode> node,
38 float factor) {
39 if (!node->IsLeaf()) {
40 return base::MakeRefCounted<CalculationExpressionMultiplicationNode>(
41 std::move(node), factor);
42 }
43 const auto& leaf = To<CalculationExpressionLeafNode>(*node);
44 PixelsAndPercent value(leaf.Pixels() * factor, leaf.Percent() * factor);
45 return base::MakeRefCounted<CalculationExpressionLeafNode>(value);
46 }
47
Evaluate(float max_value) const48 float CalculationExpressionMultiplicationNode::Evaluate(float max_value) const {
49 return child_->Evaluate(max_value) * factor_;
50 }
51
operator ==(const CalculationExpressionNode & other) const52 bool CalculationExpressionMultiplicationNode::operator==(
53 const CalculationExpressionNode& other) const {
54 if (!other.IsMultiplication())
55 return false;
56 const auto& other_multiply =
57 To<CalculationExpressionMultiplicationNode>(other);
58 return factor_ == other_multiply.factor_ && *child_ == *other_multiply.child_;
59 }
60
61 scoped_refptr<const CalculationExpressionNode>
Zoom(double factor) const62 CalculationExpressionMultiplicationNode::Zoom(double factor) const {
63 return CreateSimplified(child_->Zoom(factor), factor_);
64 }
65
66 // ------ CalculationExpressionAdditiveNode ------
67
68 // static
69 scoped_refptr<const CalculationExpressionNode>
CreateSimplified(scoped_refptr<const CalculationExpressionNode> lhs,scoped_refptr<const CalculationExpressionNode> rhs,Type type)70 CalculationExpressionAdditiveNode::CreateSimplified(
71 scoped_refptr<const CalculationExpressionNode> lhs,
72 scoped_refptr<const CalculationExpressionNode> rhs,
73 Type type) {
74 if (!lhs->IsLeaf() || !rhs->IsLeaf()) {
75 return base::MakeRefCounted<CalculationExpressionAdditiveNode>(
76 std::move(lhs), std::move(rhs), type);
77 }
78 const auto& left_leaf = To<CalculationExpressionLeafNode>(*lhs);
79 const auto& right_leaf = To<CalculationExpressionLeafNode>(*rhs);
80 PixelsAndPercent value = left_leaf.GetPixelsAndPercent();
81 if (type == Type::kAdd) {
82 value.pixels += right_leaf.Pixels();
83 value.percent += right_leaf.Percent();
84 } else {
85 value.pixels -= right_leaf.Pixels();
86 value.percent -= right_leaf.Percent();
87 }
88 return base::MakeRefCounted<CalculationExpressionLeafNode>(value);
89 }
90
Evaluate(float max_value) const91 float CalculationExpressionAdditiveNode::Evaluate(float max_value) const {
92 if (IsAdd())
93 return lhs_->Evaluate(max_value) + rhs_->Evaluate(max_value);
94 if (IsSubtract())
95 return lhs_->Evaluate(max_value) - rhs_->Evaluate(max_value);
96 NOTREACHED();
97 return 0;
98 }
99
operator ==(const CalculationExpressionNode & other) const100 bool CalculationExpressionAdditiveNode::operator==(
101 const CalculationExpressionNode& other) const {
102 if (!other.IsAdditive())
103 return false;
104 const auto& other_add_subtract = To<CalculationExpressionAdditiveNode>(other);
105 // Do we need to consider add as commutative?
106 return type_ == other_add_subtract.type_ &&
107 *lhs_ == *other_add_subtract.lhs_ && *rhs_ == *other_add_subtract.rhs_;
108 }
109
110 scoped_refptr<const CalculationExpressionNode>
Zoom(double factor) const111 CalculationExpressionAdditiveNode::Zoom(double factor) const {
112 return CreateSimplified(lhs_->Zoom(factor), rhs_->Zoom(factor), type_);
113 }
114
115 // ------ CalculationExpressionComparisonNode ------
116
117 // static
118 scoped_refptr<const CalculationExpressionNode>
CreateSimplified(Vector<scoped_refptr<const CalculationExpressionNode>> && operands,Type type)119 CalculationExpressionComparisonNode::CreateSimplified(
120 Vector<scoped_refptr<const CalculationExpressionNode>>&& operands,
121 Type type) {
122 DCHECK(operands.size());
123 float simplified_px;
124 bool can_simplify = true;
125 for (wtf_size_t i = 0; i < operands.size(); ++i) {
126 const auto* leaf = DynamicTo<CalculationExpressionLeafNode>(*operands[i]);
127 if (!leaf || leaf->Percent()) {
128 can_simplify = false;
129 break;
130 }
131 if (!i) {
132 simplified_px = leaf->Pixels();
133 } else {
134 if (type == Type::kMin)
135 simplified_px = std::min(simplified_px, leaf->Pixels());
136 else
137 simplified_px = std::max(simplified_px, leaf->Pixels());
138 }
139 }
140 if (can_simplify) {
141 return base::MakeRefCounted<CalculationExpressionLeafNode>(
142 PixelsAndPercent(simplified_px, 0));
143 }
144 return base::MakeRefCounted<CalculationExpressionComparisonNode>(
145 std::move(operands), type);
146 }
147
Evaluate(float max_value) const148 float CalculationExpressionComparisonNode::Evaluate(float max_value) const {
149 float result = operands_.front()->Evaluate(max_value);
150 if (IsMin()) {
151 for (wtf_size_t i = 1; i < operands_.size(); ++i)
152 result = std::min(result, operands_[i]->Evaluate(max_value));
153 } else if (IsMax()) {
154 for (wtf_size_t i = 1; i < operands_.size(); ++i)
155 result = std::max(result, operands_[i]->Evaluate(max_value));
156 } else {
157 NOTREACHED();
158 }
159 return result;
160 }
161
operator ==(const CalculationExpressionNode & other) const162 bool CalculationExpressionComparisonNode::operator==(
163 const CalculationExpressionNode& other) const {
164 if (!other.IsComparison())
165 return false;
166 const auto& other_comparison = To<CalculationExpressionComparisonNode>(other);
167 if (type_ != other_comparison.type_)
168 return false;
169 if (operands_.size() != other_comparison.operands_.size())
170 return false;
171 // We may consider ignoring operand ordering to allow better memory
172 // optimization. The code complexity might not pay off, though.
173 for (wtf_size_t i = 0; i < operands_.size(); ++i) {
174 if (*operands_[i] != *other_comparison.operands_[i])
175 return false;
176 }
177 return true;
178 }
179
180 scoped_refptr<const CalculationExpressionNode>
Zoom(double factor) const181 CalculationExpressionComparisonNode::Zoom(double factor) const {
182 Vector<scoped_refptr<const CalculationExpressionNode>> cloned_operands;
183 cloned_operands.ReserveCapacity(operands_.size());
184 for (const auto& operand : operands_)
185 cloned_operands.push_back(operand->Zoom(factor));
186 return CreateSimplified(std::move(cloned_operands), type_);
187 }
188
189 } // namespace blink
190