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/length.h"
6 
7 #include "testing/gtest/include/gtest/gtest.h"
8 #include "third_party/blink/renderer/platform/geometry/calculation_expression_node.h"
9 #include "third_party/blink/renderer/platform/geometry/calculation_value.h"
10 
11 namespace blink {
12 
13 namespace {
14 
15 const PixelsAndPercent ten_px(10, 0);
16 const PixelsAndPercent twenty_px(20, 0);
17 const PixelsAndPercent ten_percent(0, 10);
18 const PixelsAndPercent twenty_percent(0, 20);
19 
20 }  // namespace
21 
22 class LengthTest : public ::testing::Test {
23  public:
24   using Pointer = scoped_refptr<const CalculationExpressionNode>;
25 
Leaf(PixelsAndPercent value)26   Pointer Leaf(PixelsAndPercent value) {
27     return base::MakeRefCounted<CalculationExpressionLeafNode>(value);
28   }
29 
Add(Pointer lhs,Pointer rhs)30   Pointer Add(Pointer lhs, Pointer rhs) {
31     return base::MakeRefCounted<CalculationExpressionAdditiveNode>(
32         std::move(lhs), std::move(rhs),
33         CalculationExpressionAdditiveNode::Type::kAdd);
34   }
35 
Subtract(Pointer lhs,Pointer rhs)36   Pointer Subtract(Pointer lhs, Pointer rhs) {
37     return base::MakeRefCounted<CalculationExpressionAdditiveNode>(
38         std::move(lhs), std::move(rhs),
39         CalculationExpressionAdditiveNode::Type::kSubtract);
40   }
41 
Multiply(Pointer node,float factor)42   Pointer Multiply(Pointer node, float factor) {
43     return base::MakeRefCounted<CalculationExpressionMultiplicationNode>(
44         std::move(node), factor);
45   }
46 
Min(Pointer op1,Pointer op2)47   Pointer Min(Pointer op1, Pointer op2) {
48     Vector<Pointer> operands;
49     operands.push_back(std::move(op1));
50     operands.push_back(std::move(op2));
51     return base::MakeRefCounted<CalculationExpressionComparisonNode>(
52         std::move(operands), CalculationExpressionComparisonNode::Type::kMin);
53   }
54 
Max(Pointer op1,Pointer op2)55   Pointer Max(Pointer op1, Pointer op2) {
56     Vector<Pointer> operands;
57     operands.push_back(std::move(op1));
58     operands.push_back(std::move(op2));
59     return base::MakeRefCounted<CalculationExpressionComparisonNode>(
60         std::move(operands), CalculationExpressionComparisonNode::Type::kMax);
61   }
62 
CreateLength(Pointer expression)63   Length CreateLength(Pointer expression) {
64     return Length(CalculationValue::CreateSimplified(std::move(expression),
65                                                      kValueRangeAll));
66   }
67 };
68 
TEST_F(LengthTest,EvaluateSimpleComparison)69 TEST_F(LengthTest, EvaluateSimpleComparison) {
70   // min(10px, 20px)
71   {
72     Length length = CreateLength(Min(Leaf(ten_px), Leaf(twenty_px)));
73     EXPECT_EQ(10.0f, length.GetCalculationValue().Evaluate(-200));
74     EXPECT_EQ(10.0f, length.GetCalculationValue().Evaluate(-100));
75     EXPECT_EQ(10.0f, length.GetCalculationValue().Evaluate(0));
76     EXPECT_EQ(10.0f, length.GetCalculationValue().Evaluate(100));
77     EXPECT_EQ(10.0f, length.GetCalculationValue().Evaluate(200));
78   }
79 
80   // min(10%, 20%)
81   {
82     Length length = CreateLength(Min(Leaf(ten_percent), Leaf(twenty_percent)));
83     EXPECT_EQ(-40.0f, length.GetCalculationValue().Evaluate(-200));
84     EXPECT_EQ(-20.0f, length.GetCalculationValue().Evaluate(-100));
85     EXPECT_EQ(0.0f, length.GetCalculationValue().Evaluate(0));
86     EXPECT_EQ(10.0f, length.GetCalculationValue().Evaluate(100));
87     EXPECT_EQ(20.0f, length.GetCalculationValue().Evaluate(200));
88   }
89 
90   // min(10px, 10%)
91   {
92     Length length = CreateLength(Min(Leaf(ten_px), Leaf(twenty_percent)));
93     EXPECT_EQ(-40.0f, length.GetCalculationValue().Evaluate(-200));
94     EXPECT_EQ(-20.0f, length.GetCalculationValue().Evaluate(-100));
95     EXPECT_EQ(0.0f, length.GetCalculationValue().Evaluate(0));
96     EXPECT_EQ(10.0f, length.GetCalculationValue().Evaluate(100));
97     EXPECT_EQ(10.0f, length.GetCalculationValue().Evaluate(200));
98   }
99 
100   // max(10px, 20px)
101   {
102     Length length = CreateLength(Max(Leaf(ten_px), Leaf(twenty_px)));
103     EXPECT_EQ(20.0f, length.GetCalculationValue().Evaluate(-200));
104     EXPECT_EQ(20.0f, length.GetCalculationValue().Evaluate(-100));
105     EXPECT_EQ(20.0f, length.GetCalculationValue().Evaluate(0));
106     EXPECT_EQ(20.0f, length.GetCalculationValue().Evaluate(100));
107     EXPECT_EQ(20.0f, length.GetCalculationValue().Evaluate(200));
108   }
109 
110   // max(10%, 20%)
111   {
112     Length length = CreateLength(Max(Leaf(ten_percent), Leaf(twenty_percent)));
113     EXPECT_EQ(-20.0f, length.GetCalculationValue().Evaluate(-200));
114     EXPECT_EQ(-10.0f, length.GetCalculationValue().Evaluate(-100));
115     EXPECT_EQ(0.0f, length.GetCalculationValue().Evaluate(0));
116     EXPECT_EQ(20.0f, length.GetCalculationValue().Evaluate(100));
117     EXPECT_EQ(40.0f, length.GetCalculationValue().Evaluate(200));
118   }
119 
120   // max(10px, 10%)
121   {
122     Length length = CreateLength(Max(Leaf(ten_px), Leaf(ten_percent)));
123     EXPECT_EQ(10.0f, length.GetCalculationValue().Evaluate(-200));
124     EXPECT_EQ(10.0f, length.GetCalculationValue().Evaluate(-100));
125     EXPECT_EQ(10.0f, length.GetCalculationValue().Evaluate(0));
126     EXPECT_EQ(10.0f, length.GetCalculationValue().Evaluate(100));
127     EXPECT_EQ(20.0f, length.GetCalculationValue().Evaluate(200));
128   }
129 }
130 
TEST_F(LengthTest,EvaluateNestedComparisons)131 TEST_F(LengthTest, EvaluateNestedComparisons) {
132   // max(10px, min(10%, 20px))
133   {
134     Length length = CreateLength(
135         Max(Leaf(ten_px), Min(Leaf(ten_percent), Leaf(twenty_px))));
136     EXPECT_EQ(10.0f, length.GetCalculationValue().Evaluate(50));
137     EXPECT_EQ(15.0f, length.GetCalculationValue().Evaluate(150));
138     EXPECT_EQ(20.0f, length.GetCalculationValue().Evaluate(250));
139   }
140 
141   // max(10%, min(10px, 20%))
142   {
143     Length length = CreateLength(
144         Max(Leaf(ten_percent), Min(Leaf(ten_px), Leaf(twenty_percent))));
145     EXPECT_EQ(5.0f, length.GetCalculationValue().Evaluate(25));
146     EXPECT_EQ(10.0f, length.GetCalculationValue().Evaluate(50));
147     EXPECT_EQ(10.0f, length.GetCalculationValue().Evaluate(75));
148     EXPECT_EQ(10.0f, length.GetCalculationValue().Evaluate(100));
149     EXPECT_EQ(12.5f, length.GetCalculationValue().Evaluate(125));
150   }
151 
152   // min(max(10px, 10%), 20px)
153   {
154     Length length = CreateLength(
155         Min(Max(Leaf(ten_px), Leaf(ten_percent)), Leaf(twenty_px)));
156     EXPECT_EQ(10.0f, length.GetCalculationValue().Evaluate(50));
157     EXPECT_EQ(15.0f, length.GetCalculationValue().Evaluate(150));
158     EXPECT_EQ(20.0f, length.GetCalculationValue().Evaluate(250));
159   }
160 
161   // min(max(10%, 10px), 20%)
162   {
163     Length length = CreateLength(
164         Min(Max(Leaf(ten_percent), Leaf(ten_px)), Leaf(twenty_percent)));
165     EXPECT_EQ(5.0f, length.GetCalculationValue().Evaluate(25));
166     EXPECT_EQ(10.0f, length.GetCalculationValue().Evaluate(50));
167     EXPECT_EQ(10.0f, length.GetCalculationValue().Evaluate(75));
168     EXPECT_EQ(10.0f, length.GetCalculationValue().Evaluate(100));
169     EXPECT_EQ(12.5f, length.GetCalculationValue().Evaluate(125));
170   }
171 }
172 
TEST_F(LengthTest,EvaluateAdditive)173 TEST_F(LengthTest, EvaluateAdditive) {
174   // min(10%, 10px) + 10px
175   {
176     Length length =
177         CreateLength(Add(Min(Leaf(ten_percent), Leaf(ten_px)), Leaf(ten_px)));
178     EXPECT_EQ(15.0f, length.GetCalculationValue().Evaluate(50));
179     EXPECT_EQ(20.0f, length.GetCalculationValue().Evaluate(100));
180     EXPECT_EQ(20.0f, length.GetCalculationValue().Evaluate(150));
181   }
182 
183   // min(10%, 10px) - 10px
184   {
185     Length length = CreateLength(
186         Subtract(Min(Leaf(ten_percent), Leaf(ten_px)), Leaf(ten_px)));
187     EXPECT_EQ(-5.0f, length.GetCalculationValue().Evaluate(50));
188     EXPECT_EQ(0.0f, length.GetCalculationValue().Evaluate(100));
189     EXPECT_EQ(0.0f, length.GetCalculationValue().Evaluate(150));
190   }
191 
192   // 10px + max(10%, 10px)
193   {
194     Length length =
195         CreateLength(Add(Leaf(ten_px), Max(Leaf(ten_percent), Leaf(ten_px))));
196     EXPECT_EQ(20.0f, length.GetCalculationValue().Evaluate(50));
197     EXPECT_EQ(20.0f, length.GetCalculationValue().Evaluate(100));
198     EXPECT_EQ(25.0f, length.GetCalculationValue().Evaluate(150));
199   }
200 
201   // 10px - max(10%, 10px)
202   {
203     Length length = CreateLength(
204         Subtract(Leaf(ten_px), Max(Leaf(ten_percent), Leaf(ten_px))));
205     EXPECT_EQ(0.0f, length.GetCalculationValue().Evaluate(50));
206     EXPECT_EQ(0.0f, length.GetCalculationValue().Evaluate(100));
207     EXPECT_EQ(-5.0f, length.GetCalculationValue().Evaluate(150));
208   }
209 }
210 
TEST_F(LengthTest,EvaluateMultiplicative)211 TEST_F(LengthTest, EvaluateMultiplicative) {
212   // min(10px, 10%) * 2
213   {
214     Length length =
215         CreateLength(Multiply(Min(Leaf(ten_px), Leaf(ten_percent)), 2));
216     EXPECT_EQ(10.0f, length.GetCalculationValue().Evaluate(50));
217     EXPECT_EQ(20.0f, length.GetCalculationValue().Evaluate(100));
218     EXPECT_EQ(20.0f, length.GetCalculationValue().Evaluate(150));
219   }
220 
221   // max(10px, 10%) * 0.5
222   {
223     Length length =
224         CreateLength(Multiply(Max(Leaf(ten_px), Leaf(ten_percent)), 0.5));
225     EXPECT_EQ(5.0f, length.GetCalculationValue().Evaluate(50));
226     EXPECT_EQ(5.0f, length.GetCalculationValue().Evaluate(100));
227     EXPECT_EQ(10.0f, length.GetCalculationValue().Evaluate(200));
228   }
229 }
230 
TEST_F(LengthTest,BlendExpressions)231 TEST_F(LengthTest, BlendExpressions) {
232   // From: min(10px, 20%)
233   // To: max(20px, 10%)
234   // Progress: 0.25
235 
236   Length from_length = CreateLength(Min(Leaf(ten_px), Leaf(twenty_percent)));
237   Length to_length = CreateLength(Max(Leaf(twenty_px), Leaf(ten_percent)));
238   Length blended = to_length.Blend(from_length, 0.25, kValueRangeAll);
239 
240   EXPECT_EQ(8.75f, blended.GetCalculationValue().Evaluate(25));
241   EXPECT_EQ(12.5f, blended.GetCalculationValue().Evaluate(50));
242   EXPECT_EQ(12.5f, blended.GetCalculationValue().Evaluate(100));
243   EXPECT_EQ(12.5f, blended.GetCalculationValue().Evaluate(200));
244   EXPECT_EQ(17.5f, blended.GetCalculationValue().Evaluate(400));
245 }
246 
TEST_F(LengthTest,ZoomExpression)247 TEST_F(LengthTest, ZoomExpression) {
248   // Original: min(10px, 10%)
249   // Factor: 2.0
250   {
251     Length original = CreateLength(Min(Leaf(ten_px), Leaf(ten_percent)));
252     Length zoomed = original.Zoom(2);
253     EXPECT_EQ(10.0f, zoomed.GetCalculationValue().Evaluate(100));
254     EXPECT_EQ(20.0f, zoomed.GetCalculationValue().Evaluate(200));
255     EXPECT_EQ(20.0f, zoomed.GetCalculationValue().Evaluate(400));
256   }
257 
258   // Original: max(10px, 10%)
259   // Factor: 0.5
260   {
261     Length original = CreateLength(Max(Leaf(ten_px), Leaf(ten_percent)));
262     Length zoomed = original.Zoom(0.5);
263     EXPECT_EQ(5.0f, zoomed.GetCalculationValue().Evaluate(25));
264     EXPECT_EQ(5.0f, zoomed.GetCalculationValue().Evaluate(50));
265     EXPECT_EQ(10.0f, zoomed.GetCalculationValue().Evaluate(100));
266   }
267 }
268 
TEST_F(LengthTest,SubtractExpressionFromOneHundredPercent)269 TEST_F(LengthTest, SubtractExpressionFromOneHundredPercent) {
270   // min(10px, 20%)
271   {
272     Length original = CreateLength(Min(Leaf(ten_px), Leaf(twenty_percent)));
273     Length result = original.SubtractFromOneHundredPercent();
274     EXPECT_EQ(20.0f, result.GetCalculationValue().Evaluate(25));
275     EXPECT_EQ(40.0f, result.GetCalculationValue().Evaluate(50));
276     EXPECT_EQ(90.0f, result.GetCalculationValue().Evaluate(100));
277   }
278 
279   // max(20px, 10%)
280   {
281     Length original = CreateLength(Max(Leaf(twenty_px), Leaf(ten_percent)));
282     Length result = original.SubtractFromOneHundredPercent();
283     EXPECT_EQ(80.0f, result.GetCalculationValue().Evaluate(100));
284     EXPECT_EQ(180.0f, result.GetCalculationValue().Evaluate(200));
285     EXPECT_EQ(360.0f, result.GetCalculationValue().Evaluate(400));
286   }
287 }
288 
289 }  // namespace blink
290