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