Commit 7855d607 authored by Xiaocheng Hu's avatar Xiaocheng Hu Committed by Commit Bot

Avoid length array conversion in CSSTransformInterpolationType

Currently, CSSTransformInterpolationType calls AccumulateLengthArray()
only to obtain the length unit types involved in a <length> value, which
is an overkill. Hence, this patch changes it into obtaining the types
only.

This also unblocks the code from working on <length> values involving
min/max, as these values cannot be converted into a length array.

Bug: 991672
Change-Id: Ib2865be502e2306fdbf2e1b5f4bafe26047ed5bc
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1775424Reviewed-by: default avatarEmil A Eklund <eae@chromium.org>
Reviewed-by: default avatarAlan Cutter <alancutter@chromium.org>
Commit-Queue: Xiaocheng Hu <xiaochengh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#691864}
parent e1830003
......@@ -222,27 +222,23 @@ InterpolationValue CSSTransformInterpolationType::MaybeConvertValue(
ConversionCheckers& conversion_checkers) const {
DCHECK(state);
if (auto* list_value = DynamicTo<CSSValueList>(value)) {
CSSLengthArray length_array;
CSSPrimitiveValue::LengthTypeFlags types;
for (const CSSValue* item : *list_value) {
const auto& transform_function = To<CSSFunctionValue>(*item);
if (transform_function.FunctionType() == CSSValueID::kMatrix ||
transform_function.FunctionType() == CSSValueID::kMatrix3d) {
length_array.type_flags.set(CSSPrimitiveValue::kUnitTypePixels);
types.set(CSSPrimitiveValue::kUnitTypePixels);
continue;
}
for (const CSSValue* argument : transform_function) {
const auto& primitive_value = To<CSSPrimitiveValue>(*argument);
if (!primitive_value.IsLength())
continue;
if (!primitive_value.AccumulateLengthArray(length_array)) {
// TODO(crbug.com/991672): Implement interpolation when CSS comparison
// functions min/max are involved.
return nullptr;
}
primitive_value.AccumulateLengthUnitTypes(types);
}
}
std::unique_ptr<InterpolationType::ConversionChecker> length_units_checker =
LengthUnitsChecker::MaybeCreate(std::move(length_array), *state);
LengthUnitsChecker::MaybeCreate(types, *state);
if (length_units_checker)
conversion_checkers.push_back(std::move(length_units_checker));
......
......@@ -18,15 +18,16 @@ namespace blink {
class LengthUnitsChecker : public CSSInterpolationType::CSSConversionChecker {
public:
static std::unique_ptr<LengthUnitsChecker> MaybeCreate(
CSSLengthArray&& length_array,
const CSSPrimitiveValue::LengthTypeFlags& length_types,
const StyleResolverState& state) {
bool create = false;
wtf_size_t last_index = 0;
for (wtf_size_t i = 0; i < length_array.values.size(); i++) {
if (i == CSSPrimitiveValue::kUnitTypePercentage ||
!length_array.type_flags[i])
CSSLengthArray length_array;
for (wtf_size_t i = 0; i < length_types.size(); ++i) {
if (i == CSSPrimitiveValue::kUnitTypePercentage || !length_types[i])
continue;
length_array.values[i] = LengthUnit(i, state.CssToLengthConversionData());
length_array.type_flags.set(i);
create = true;
last_index = i;
}
......
......@@ -239,6 +239,11 @@ bool CSSMathExpressionNumericLiteral::AccumulateLengthArray(
return value_->AccumulateLengthArray(length_array, multiplier);
}
void CSSMathExpressionNumericLiteral::AccumulateLengthUnitTypes(
CSSPrimitiveValue::LengthTypeFlags& types) const {
value_->AccumulateLengthUnitTypes(types);
}
bool CSSMathExpressionNumericLiteral::operator==(
const CSSMathExpressionNode& other) const {
if (!other.IsNumericLiteral())
......@@ -587,6 +592,12 @@ bool CSSMathExpressionBinaryOperation::AccumulateLengthArray(
}
}
void CSSMathExpressionBinaryOperation::AccumulateLengthUnitTypes(
CSSPrimitiveValue::LengthTypeFlags& types) const {
left_side_->AccumulateLengthUnitTypes(types);
right_side_->AccumulateLengthUnitTypes(types);
}
bool CSSMathExpressionBinaryOperation::IsComputationallyIndependent() const {
if (Category() != kCalcLength && Category() != kCalcPercentLength)
return true;
......@@ -842,6 +853,12 @@ bool CSSMathExpressionVariadicOperation::AccumulateLengthArray(CSSLengthArray&,
return false;
}
void CSSMathExpressionVariadicOperation::AccumulateLengthUnitTypes(
CSSPrimitiveValue::LengthTypeFlags& types) const {
for (const auto& operand : operands_)
operand->AccumulateLengthUnitTypes(types);
}
bool CSSMathExpressionVariadicOperation::IsComputationallyIndependent() const {
for (const auto& operand : operands_) {
if (!operand->IsComputationallyIndependent())
......
......@@ -89,6 +89,8 @@ class CORE_EXPORT CSSMathExpressionNode
virtual double ComputeLengthPx(const CSSToLengthConversionData&) const = 0;
virtual bool AccumulateLengthArray(CSSLengthArray&,
double multiplier) const = 0;
virtual void AccumulateLengthUnitTypes(
CSSPrimitiveValue::LengthTypeFlags& types) const = 0;
virtual scoped_refptr<const CalculationExpressionNode>
ToCalculationExpression(const CSSToLengthConversionData&) const = 0;
......@@ -167,6 +169,8 @@ class CORE_EXPORT CSSMathExpressionNumericLiteral final
const CSSToLengthConversionData& conversion_data) const final;
bool AccumulateLengthArray(CSSLengthArray& length_array,
double multiplier) const final;
void AccumulateLengthUnitTypes(
CSSPrimitiveValue::LengthTypeFlags& types) const final;
bool IsComputationallyIndependent() const final;
bool operator==(const CSSMathExpressionNode& other) const final;
CSSPrimitiveValue::UnitType ResolvedUnitType() const final;
......@@ -220,6 +224,8 @@ class CORE_EXPORT CSSMathExpressionBinaryOperation final
const CSSToLengthConversionData& conversion_data) const final;
bool AccumulateLengthArray(CSSLengthArray& length_array,
double multiplier) const final;
void AccumulateLengthUnitTypes(
CSSPrimitiveValue::LengthTypeFlags& types) const final;
bool IsComputationallyIndependent() const final;
String CustomCSSText() const final;
bool operator==(const CSSMathExpressionNode& exp) const final;
......@@ -285,6 +291,8 @@ class CSSMathExpressionVariadicOperation final : public CSSMathExpressionNode {
const CSSToLengthConversionData& conversion_data) const final;
bool AccumulateLengthArray(CSSLengthArray& length_array,
double multiplier) const final;
void AccumulateLengthUnitTypes(
CSSPrimitiveValue::LengthTypeFlags& types) const final;
base::Optional<double> ComputeValueInCanonicalUnit() const final;
bool IsComputationallyIndependent() const final;
bool operator==(const CSSMathExpressionNode& other) const final;
......
......@@ -80,6 +80,10 @@ class CORE_EXPORT CSSMathFunctionValue : public CSSPrimitiveValue {
Length ConvertToLength(
const CSSToLengthConversionData& conversion_data) const;
void AccumulateLengthUnitTypes(LengthTypeFlags& types) const {
expression_->AccumulateLengthUnitTypes(types);
}
String CustomCSSText() const;
bool Equals(const CSSMathFunctionValue& other) const;
......
......@@ -126,6 +126,16 @@ bool CSSNumericLiteralValue::AccumulateLengthArray(CSSLengthArray& length_array,
return true;
}
void CSSNumericLiteralValue::AccumulateLengthUnitTypes(
LengthTypeFlags& types) const {
if (!IsLength())
return;
LengthUnitType length_type;
bool conversion_success = UnitTypeToLengthUnitType(GetType(), length_type);
DCHECK(conversion_success);
types.set(length_type);
}
bool CSSNumericLiteralValue::IsComputationallyIndependent() const {
if (!IsLength())
return true;
......
......@@ -58,6 +58,7 @@ class CORE_EXPORT CSSNumericLiteralValue : public CSSPrimitiveValue {
const CSSToLengthConversionData& conversion_data) const;
bool AccumulateLengthArray(CSSLengthArray& length_array,
double multiplier) const;
void AccumulateLengthUnitTypes(LengthTypeFlags& types) const;
String CustomCSSText() const;
bool Equals(const CSSNumericLiteralValue& other) const;
......
......@@ -289,6 +289,13 @@ bool CSSPrimitiveValue::AccumulateLengthArray(CSSLengthArray& length_array,
multiplier);
}
void CSSPrimitiveValue::AccumulateLengthUnitTypes(
LengthTypeFlags& types) const {
if (IsCalculated())
return To<CSSMathFunctionValue>(this)->AccumulateLengthUnitTypes(types);
To<CSSNumericLiteralValue>(this)->AccumulateLengthUnitTypes(types);
}
double CSSPrimitiveValue::ConversionToCanonicalUnitsScaleFactor(
UnitType unit_type) {
double factor = 1.0;
......
......@@ -130,18 +130,22 @@ class CORE_EXPORT CSSPrimitiveValue : public CSSValue {
kLengthUnitTypeCount,
};
using LengthTypeFlags = std::bitset<kLengthUnitTypeCount>;
struct CSSLengthArray {
CSSLengthArray() : values(kLengthUnitTypeCount) {
}
Vector<double, CSSPrimitiveValue::kLengthUnitTypeCount> values;
std::bitset<kLengthUnitTypeCount> type_flags;
LengthTypeFlags type_flags;
};
// Returns false if the value cannot be represented as a length array, which
// happens when comparisons are involved (e.g., max(10px, 10%)).
bool AccumulateLengthArray(CSSLengthArray&, double multiplier = 1) const;
// Returns all types of length units involved in this value.
void AccumulateLengthUnitTypes(LengthTypeFlags& types) const;
enum UnitCategory {
kUNumber,
kUPercent,
......
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