Commit a6e47206 authored by Xiaocheng Hu's avatar Xiaocheng Hu Committed by Commit Bot

Add expression representation to InterpolableLength

This is a second attempt of crrev.com/c/1777025, as the previous
attempt led to a performance regression.

As CSSLengthArray cannot represent all lengths, and in particular,
cannot represent lengths where min/max() are present, this patch
augments InterpolableLength with a CSSMathExpressionNode representation,
so that all lengths can be interpolated and animated.

Bug: 991672, 1002177
Change-Id: Ic8af313872b900eac2587531c56a8eca65d55a5f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1805718Reviewed-by: default avatarRune Lillesveen <futhark@chromium.org>
Reviewed-by: default avatarAlan Cutter <alancutter@chromium.org>
Commit-Queue: Xiaocheng Hu <xiaochengh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#698895}
parent 6280e33c
...@@ -10,19 +10,19 @@ ...@@ -10,19 +10,19 @@
#include "third_party/blink/renderer/core/animation/pairwise_interpolation_value.h" #include "third_party/blink/renderer/core/animation/pairwise_interpolation_value.h"
#include "third_party/blink/renderer/core/css/css_primitive_value.h" #include "third_party/blink/renderer/core/css/css_primitive_value.h"
#include "third_party/blink/renderer/platform/geometry/length.h" #include "third_party/blink/renderer/platform/geometry/length.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/wtf/casting.h" #include "third_party/blink/renderer/platform/wtf/casting.h"
namespace blink { namespace blink {
class CSSToLengthConversionData; class CSSToLengthConversionData;
class CSSMathExpressionNode;
class CORE_EXPORT InterpolableLength final : public InterpolableValue { class CORE_EXPORT InterpolableLength final : public InterpolableValue {
public: public:
~InterpolableLength() final {} ~InterpolableLength() final {}
InterpolableLength(const CSSLengthArray& length_array) InterpolableLength(CSSLengthArray&& length_array);
: length_array_(length_array) {} explicit InterpolableLength(const CSSMathExpressionNode& expression);
InterpolableLength(CSSLengthArray&& length_array)
: length_array_(std::move(length_array)) {}
static std::unique_ptr<InterpolableLength> CreatePixels(double pixels); static std::unique_ptr<InterpolableLength> CreatePixels(double pixels);
static std::unique_ptr<InterpolableLength> CreatePercent(double pixels); static std::unique_ptr<InterpolableLength> CreatePercent(double pixels);
...@@ -45,10 +45,8 @@ class CORE_EXPORT InterpolableLength final : public InterpolableValue { ...@@ -45,10 +45,8 @@ class CORE_EXPORT InterpolableLength final : public InterpolableValue {
// expressions. // expressions.
const CSSPrimitiveValue* CreateCSSValue(ValueRange range) const; const CSSPrimitiveValue* CreateCSSValue(ValueRange range) const;
bool HasPercentage() const { void SetHasPercentage();
return length_array_.type_flags.test( bool HasPercentage() const;
CSSPrimitiveValue::kUnitTypePercentage);
}
void SubtractFromOneHundredPercent(); void SubtractFromOneHundredPercent();
// InterpolableValue: // InterpolableValue:
...@@ -57,17 +55,11 @@ class CORE_EXPORT InterpolableLength final : public InterpolableValue { ...@@ -57,17 +55,11 @@ class CORE_EXPORT InterpolableLength final : public InterpolableValue {
NOTREACHED(); NOTREACHED();
return false; return false;
} }
std::unique_ptr<InterpolableValue> Clone() const final { std::unique_ptr<InterpolableValue> Clone() const final;
return std::make_unique<InterpolableLength>(length_array_);
}
std::unique_ptr<InterpolableValue> CloneAndZero() const final { std::unique_ptr<InterpolableValue> CloneAndZero() const final {
return std::make_unique<InterpolableLength>(CSSLengthArray()); return std::make_unique<InterpolableLength>(CSSLengthArray());
} }
void Scale(double scale) final { void Scale(double scale) final;
for (double& value : length_array_.values) {
value *= scale;
}
}
void ScaleAndAdd(double scale, const InterpolableValue& other) final; void ScaleAndAdd(double scale, const InterpolableValue& other) final;
void AssertCanInterpolateWith(const InterpolableValue& other) const final; void AssertCanInterpolateWith(const InterpolableValue& other) const final;
...@@ -77,7 +69,17 @@ class CORE_EXPORT InterpolableLength final : public InterpolableValue { ...@@ -77,7 +69,17 @@ class CORE_EXPORT InterpolableLength final : public InterpolableValue {
const double progress, const double progress,
InterpolableValue& result) const final; InterpolableValue& result) const final;
bool IsLengthArray() const { return type_ == Type::kLengthArray; }
bool IsExpression() const { return type_ == Type::kExpression; }
void SetLengthArray(CSSLengthArray&& length_array);
void SetExpression(const CSSMathExpressionNode& expression);
const CSSMathExpressionNode& AsExpression() const;
enum class Type { kLengthArray, kExpression };
Type type_;
CSSLengthArray length_array_; CSSLengthArray length_array_;
Persistent<const CSSMathExpressionNode> expression_;
}; };
template <> template <>
......
...@@ -120,6 +120,11 @@ class CORE_EXPORT CSSMathExpressionNode ...@@ -120,6 +120,11 @@ class CORE_EXPORT CSSMathExpressionNode
virtual bool IsComputationallyIndependent() const = 0; virtual bool IsComputationallyIndependent() const = 0;
CalculationCategory Category() const { return category_; } CalculationCategory Category() const { return category_; }
bool HasPercentage() const {
return category_ == kCalcPercent || category_ == kCalcPercentNumber ||
category_ == kCalcPercentLength ||
category_ == kCalcPercentLengthNumber;
}
// Returns the unit type of the math expression *without doing any type // Returns the unit type of the math expression *without doing any type
// conversion* (e.g., 1px + 1em needs type conversion to resolve). // conversion* (e.g., 1px + 1em needs type conversion to resolve).
...@@ -164,6 +169,8 @@ class CORE_EXPORT CSSMathExpressionNumericLiteral final ...@@ -164,6 +169,8 @@ class CORE_EXPORT CSSMathExpressionNumericLiteral final
CSSMathExpressionNumericLiteral(const CSSNumericLiteralValue* value, CSSMathExpressionNumericLiteral(const CSSNumericLiteralValue* value,
bool is_integer); bool is_integer);
const CSSNumericLiteralValue& GetValue() const { return *value_; }
bool IsNumericLiteral() const final { return true; } bool IsNumericLiteral() const final { return true; }
bool IsZero() const final; bool IsZero() const final;
......
<!doctype html>
<link rel="help" href="https://drafts.csswg.org/css-values-4/#comp-func">
<link rel="author" title="Xiaocheng Hu" href="mailto:xiaochengh@chromium.org">
<link rel="match" href="../reference/ref-filled-green-100px-square-only.html">
<title>Tests interpolation between CSS comparison functions</title>
<style>
@keyframes anim {
from {
width: min(50px, 30%);
height: min(75%, 160px);
}
to {
width: max(75%, 100px);
height: max(50px, 20%);
}
}
.test {
background-color: green;
animation: anim 2000000s linear;
animation-delay: -1000000s;
}
.container {
position: absolute;
width: 200px;
height: 200px;
}
</style>
<p>Test passes if there is a filled green square.</p>
<div class="container">
<div class="test"></div>
</div>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment