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_value.h"
6
7 #include "third_party/blink/renderer/platform/geometry/blend.h"
8 #include "third_party/blink/renderer/platform/geometry/calculation_expression_node.h"
9 #include "third_party/blink/renderer/platform/wtf/size_assertions.h"
10
11 namespace blink {
12
DataUnion(scoped_refptr<const CalculationExpressionNode> expression)13 CalculationValue::DataUnion::DataUnion(
14 scoped_refptr<const CalculationExpressionNode> expression)
15 : expression(std::move(expression)) {}
16
~DataUnion()17 CalculationValue::DataUnion::~DataUnion() {
18 // Release of |expression| is left to CalculationValue::~CalculationValue().
19 }
20
21 // static
CreateSimplified(scoped_refptr<const CalculationExpressionNode> expression,ValueRange range)22 scoped_refptr<CalculationValue> CalculationValue::CreateSimplified(
23 scoped_refptr<const CalculationExpressionNode> expression,
24 ValueRange range) {
25 if (expression->IsLeaf()) {
26 return Create(
27 To<CalculationExpressionLeafNode>(*expression).GetPixelsAndPercent(),
28 range);
29 }
30 return base::AdoptRef(new CalculationValue(std::move(expression), range));
31 }
32
CalculationValue(scoped_refptr<const CalculationExpressionNode> expression,ValueRange range)33 CalculationValue::CalculationValue(
34 scoped_refptr<const CalculationExpressionNode> expression,
35 ValueRange range)
36 : data_(std::move(expression)),
37 is_expression_(true),
38 is_non_negative_(range == kValueRangeNonNegative) {}
39
~CalculationValue()40 CalculationValue::~CalculationValue() {
41 if (is_expression_)
42 data_.expression.~scoped_refptr<const CalculationExpressionNode>();
43 else
44 data_.value.~PixelsAndPercent();
45 }
46
Evaluate(float max_value) const47 float CalculationValue::Evaluate(float max_value) const {
48 float value = is_expression_ ? value = data_.expression->Evaluate(max_value)
49 : value = Pixels() + Percent() / 100 * max_value;
50 return (IsNonNegative() && value < 0) ? 0 : value;
51 }
52
operator ==(const CalculationValue & other) const53 bool CalculationValue::operator==(const CalculationValue& other) const {
54 if (IsExpression())
55 return other.IsExpression() && *data_.expression == *other.data_.expression;
56 return !other.IsExpression() && Pixels() == other.Pixels() &&
57 Percent() == other.Percent();
58 }
59
60 scoped_refptr<const CalculationExpressionNode>
GetOrCreateExpression() const61 CalculationValue::GetOrCreateExpression() const {
62 if (IsExpression())
63 return data_.expression;
64 return base::MakeRefCounted<CalculationExpressionLeafNode>(
65 GetPixelsAndPercent());
66 }
67
Blend(const CalculationValue & from,double progress,ValueRange range) const68 scoped_refptr<CalculationValue> CalculationValue::Blend(
69 const CalculationValue& from,
70 double progress,
71 ValueRange range) const {
72 if (!IsExpression() && !from.IsExpression()) {
73 PixelsAndPercent from_pixels_and_percent = from.GetPixelsAndPercent();
74 PixelsAndPercent to_pixels_and_percent = GetPixelsAndPercent();
75 const float pixels = blink::Blend(from_pixels_and_percent.pixels,
76 to_pixels_and_percent.pixels, progress);
77 const float percent = blink::Blend(from_pixels_and_percent.percent,
78 to_pixels_and_percent.percent, progress);
79 return Create(PixelsAndPercent(pixels, percent), range);
80 }
81
82 auto blended_from = CalculationExpressionMultiplicationNode::CreateSimplified(
83 from.GetOrCreateExpression(), 1.0 - progress);
84 auto blended_to = CalculationExpressionMultiplicationNode::CreateSimplified(
85 GetOrCreateExpression(), progress);
86 auto result_expression = CalculationExpressionAdditiveNode::CreateSimplified(
87 std::move(blended_from), std::move(blended_to),
88 CalculationExpressionAdditiveNode::Type::kAdd);
89 return CreateSimplified(std::move(result_expression), range);
90 }
91
92 scoped_refptr<CalculationValue>
SubtractFromOneHundredPercent() const93 CalculationValue::SubtractFromOneHundredPercent() const {
94 if (!IsExpression()) {
95 PixelsAndPercent result(-Pixels(), 100 - Percent());
96 return Create(result, kValueRangeAll);
97 }
98 auto hundred_percent = base::MakeRefCounted<CalculationExpressionLeafNode>(
99 PixelsAndPercent(0, 100));
100 auto result_expression = CalculationExpressionAdditiveNode::CreateSimplified(
101 std::move(hundred_percent), GetOrCreateExpression(),
102 CalculationExpressionAdditiveNode::Type::kSubtract);
103 return CreateSimplified(std::move(result_expression), kValueRangeAll);
104 }
105
Zoom(double factor) const106 scoped_refptr<CalculationValue> CalculationValue::Zoom(double factor) const {
107 if (!IsExpression()) {
108 PixelsAndPercent result(Pixels() * factor, Percent());
109 return Create(result, GetValueRange());
110 }
111 return CreateSimplified(data_.expression->Zoom(factor), GetValueRange());
112 }
113
114 } // namespace blink
115