Commit 89de27e2 authored by Darren Shen's avatar Darren Shen Committed by Commit Bot

[css-typed-om] Make StylePropertyMap.set work with calcs.

Currently StylePropertyMap.set doesn't actually work with calcs.
The current way to check if something is, say, a <length> is to
check its CSSStyleValue::Type. However, this doesn't return
the right value for CSSMathValues, whose types may be quite
complicated.

The correct way is to use the CSSNumericValue matching algorthms:
CSSNumericValue::MatchesLength, which also takes into account
CSSMathValues and percent hints.

This patch changes the following to make this work:

- Removed base types from CSSStyleValue::StyleValueType. A base type
  like "length" is not really a CSSStyleValue type.
- Removed unused StyleValueTypeToString.
- Changed "Percent" to "Percentage" in CSSProperties.json5 as that's
  the correct term.
- Changed make_cssom_types to use the matching algorithms from
  CSSNumericValue.

Bug: 545318
Change-Id: I16aa71a4873e9992749f0f52ba641671d109170e
Reviewed-on: https://chromium-review.googlesource.com/901002
Commit-Queue: Darren Shen <shend@chromium.org>
Reviewed-by: default avatarnainar <nainar@chromium.org>
Cr-Commit-Position: refs/heads/master@{#537206}
parent ca44fdbd
function assert_is_unit(unit, result) {
assert_class_string(result, 'CSSUnitValue',
'relative lengths must compute to a CSSUnitValue');
assert_equals(result.unit, unit, 'unit');
}
function assert_is_calc_sum(result) {
assert_class_string(result, 'CSSMathSum',
'specified calc must be a CSSMathSum');
}
const gTestSyntaxExamples = {
'<length>': {
description: 'a length',
......@@ -9,23 +20,23 @@ const gTestSyntaxExamples = {
{
description: "a negative em",
input: new CSSUnitValue(-3.14, 'em'),
defaultComputed: value => {
// 'ems' are relative units, so just check that it computes to px
assert_class_string(value, 'CSSUnitValue',
'"em" lengths must compute to a CSSUnitValue');
assert_equals(value.unit, 'px', 'unit');
}
// 'ems' are relative units, so just check that it computes to px
defaultComputed: result => assert_is_unit('px', result)
},
{
description: "a positive cm",
input: new CSSUnitValue(3.14, 'cm'),
defaultComputed: value => {
// 'cms' are relative units, so just check that it computes to px
assert_class_string(value, 'CSSUnitValue',
'"cm" lengths must compute to a CSSUnitValue');
assert_equals(value.unit, 'px', 'unit');
}
// 'cms' are relative units, so just check that it computes to px
defaultComputed: result => assert_is_unit('px', result)
},
{
description: "a calc length",
input: new CSSMathSum(new CSSUnitValue(0, 'px'), new CSSUnitValue(0, 'em')),
// Specified/computed calcs are usually simplified.
// FIXME: Test this properly
defaultSpecified: assert_is_calc_sum,
defaultComputed: result => assert_is_unit('px', result)
}
],
},
'<percentage>': {
......@@ -43,6 +54,14 @@ const gTestSyntaxExamples = {
description: "a positive percent",
input: new CSSUnitValue(3.14, 'percent')
},
{
description: "a calc percent",
input: new CSSMathSum(new CSSUnitValue(0, 'percent'), new CSSUnitValue(0, 'percent')),
// Specified/computed calcs are usually simplified.
// FIXME: Test this properly
defaultSpecified: assert_is_calc_sum,
defaultComputed: result => assert_is_unit('percent', result)
}
],
},
'<time>': {
......@@ -60,6 +79,14 @@ const gTestSyntaxExamples = {
description: "positive seconds",
input: new CSSUnitValue(3.14, 's')
},
{
description: "a calc time",
input: new CSSMathSum(new CSSUnitValue(0, 's'), new CSSUnitValue(0, 'ms')),
// Specified/computed calcs are usually simplified.
// FIXME: Test this properly
defaultSpecified: assert_is_calc_sum,
defaultComputed: result => assert_is_unit('s', result)
}
],
},
'<position>': {
......
......@@ -16,9 +16,8 @@ import template_expander
class CSSOMTypesWriter(json5_generator.Writer):
"""
Generates CSSOMTypes.cpp and CSSOMKeywords.cpp. These classes provide
utility methods for determining whether a given CSSStyleValue or
CSSKeywordValue is valid for a given CSS property. The header files live in
core/css/cssom.
utility methods for determining whether a given CSSStyleValue is valid
for a given CSS property. The header files live in core/css/cssom.
"""
def __init__(self, json5_file_paths):
super(CSSOMTypesWriter, self).__init__([])
......@@ -31,10 +30,7 @@ class CSSOMTypesWriter(json5_generator.Writer):
types = []
# Expand types
for single_type in property_['typedom_types']:
if single_type == 'Image':
types.append('URLImage')
else:
types.append(single_type)
types.append(single_type)
property_['typedom_types'] = types
# Generate Keyword ID values from keywords.
......
......@@ -9,39 +9,68 @@
#include "core/css/cssom/CSSOMKeywords.h"
#include "core/css/cssom/CSSKeywordValue.h"
#include "core/css/cssom/CSSNumericValue.h"
#include "core/css/cssom/CSSStyleValue.h"
#include "core/css/cssom/CSSUnsupportedStyleValue.h"
#include "core/css/properties/CSSProperty.h"
namespace blink {
namespace {
bool IsCSSStyleValueLength(const CSSStyleValue& value) {
if (!value.IsNumericValue())
return false;
return static_cast<const CSSNumericValue&>(value).Type().
MatchesBaseType(CSSNumericValueType::BaseType::kLength);
}
bool IsCSSStyleValueTime(const CSSStyleValue& value) {
if (!value.IsNumericValue())
return false;
return static_cast<const CSSNumericValue&>(value).Type().
MatchesBaseType(CSSNumericValueType::BaseType::kTime);
}
bool IsCSSStyleValuePercentage(const CSSStyleValue& value) {
if (!value.IsNumericValue())
return false;
return static_cast<const CSSNumericValue&>(value).Type().
MatchesPercentage();
}
bool IsCSSStyleValueImage(const CSSStyleValue& value) {
return value.GetType() == CSSStyleValue::kURLImageType;
}
bool IsCSSStyleValueTransform(const CSSStyleValue& value) {
return value.GetType() == CSSStyleValue::kTransformType;
}
bool IsCSSStyleValuePosition(const CSSStyleValue& value) {
return value.GetType() == CSSStyleValue::kPositionType;
}
}
bool CSSOMTypes::PropertyCanTake(CSSPropertyID id,
const CSSStyleValue& styleValue) {
if (styleValue.GetType() == CSSStyleValue::kKeywordType) {
const CSSStyleValue& value) {
if (value.GetType() == CSSStyleValue::kKeywordType) {
return CSSOMKeywords::ValidKeywordForProperty(
id, ToCSSKeywordValue(styleValue));
}
if (styleValue.ContainsPercent() &&
!CSSProperty::Get(id).SupportsPercentage()) {
return false;
id, ToCSSKeywordValue(value));
}
if (styleValue.GetType() == CSSStyleValue::kUnknownType) {
return ToCSSUnsupportedStyleValue(styleValue).GetProperty() == id;
if (value.GetType() == CSSStyleValue::kUnknownType) {
return ToCSSUnsupportedStyleValue(value).GetProperty() == id;
}
return CSSOMTypes::PropertyCanTakeType(id, styleValue.GetType());
}
bool CSSOMTypes::PropertyCanTakeType(CSSPropertyID id,
CSSStyleValue::StyleValueType type) {
switch (id) {
case CSSPropertyVariable:
return type == CSSStyleValue::kUnparsedType;
return value.GetType() == CSSStyleValue::kUnparsedType;
{% for property in properties if property.typedom_types %}
case {{property.property_id}}:
return (
{% for type in property.typedom_types %}
{{ "|| " if not loop.first }}type == CSSStyleValue::k{{type}}Type
{{ "|| " if not loop.first }}IsCSSStyleValue{{type}}(value)
{% endfor %}
);
{% endfor %}
......
......@@ -230,7 +230,7 @@
"Frequency",
"Length",
"Number",
"Percent",
"Percentage",
"Position",
"Resolution",
"Time",
......@@ -1035,7 +1035,7 @@
field_template: "<length>",
keywords: ["auto"],
default_value: "Length()",
typedom_types: ["Length", "Percent"],
typedom_types: ["Length", "Percentage"],
converter: "ConvertLengthOrAuto",
},
{
......@@ -1496,7 +1496,7 @@
field_template: "<length>",
keywords: ["auto", "fit-content", "min-content", "max-content"],
default_value: "Length()",
typedom_types: ["Length", "Percent"],
typedom_types: ["Length", "Percentage"],
converter: "ConvertLengthSizing",
},
{
......@@ -1579,7 +1579,7 @@
field_template: "<length>",
keywords: ["auto"],
default_value: "Length()",
typedom_types: ["Length", "Percent"],
typedom_types: ["Length", "Percentage"],
converter: "ConvertLengthOrAuto",
},
{
......@@ -1674,7 +1674,7 @@
default_value: "Length(kFixed)",
converter: "ConvertQuirkyLength",
keywords: ["auto"],
typedom_types: ["Length", "Percent"]
typedom_types: ["Length", "Percentage"]
},
{
name: "margin-left",
......@@ -1685,7 +1685,7 @@
default_value: "Length(kFixed)",
converter: "ConvertQuirkyLength",
keywords: ["auto"],
typedom_types: ["Length", "Percent"]
typedom_types: ["Length", "Percentage"]
},
{
name: "margin-right",
......@@ -1696,7 +1696,7 @@
default_value: "Length(kFixed)",
converter: "ConvertQuirkyLength",
keywords: ["auto"],
typedom_types: ["Length", "Percent"]
typedom_types: ["Length", "Percentage"]
},
{
name: "margin-top",
......@@ -1707,7 +1707,7 @@
default_value: "Length(kFixed)",
converter: "ConvertQuirkyLength",
keywords: ["auto"],
typedom_types: ["Length", "Percent"]
typedom_types: ["Length", "Percentage"]
},
{
name: "marker-end",
......@@ -2030,7 +2030,7 @@
field_template: "<length>",
default_value: "Length(kFixed)",
converter: "ConvertLength",
typedom_types: ["Length", "Percent"]
typedom_types: ["Length", "Percentage"]
},
{
name: "padding-left",
......@@ -2040,7 +2040,7 @@
field_template: "<length>",
default_value: "Length(kFixed)",
converter: "ConvertLength",
typedom_types: ["Length", "Percent"]
typedom_types: ["Length", "Percentage"]
},
{
name: "padding-right",
......@@ -2050,7 +2050,7 @@
field_template: "<length>",
default_value: "Length(kFixed)",
converter: "ConvertLength",
typedom_types: ["Length", "Percent"]
typedom_types: ["Length", "Percentage"]
},
{
name: "padding-top",
......@@ -2060,7 +2060,7 @@
field_template: "<length>",
default_value: "Length(kFixed)",
converter: "ConvertLength",
typedom_types: ["Length", "Percent"]
typedom_types: ["Length", "Percentage"]
},
{
name: "paint-order",
......@@ -2142,7 +2142,7 @@
field_template: "<length>",
keywords: ["auto"],
default_value: "Length()",
typedom_types: ["Length", "Percent"],
typedom_types: ["Length", "Percentage"],
converter: "ConvertLengthOrAuto",
},
{
......@@ -2269,7 +2269,7 @@
property_methods: ["ParseSingleValue"],
runtime_flag: "CSSScrollSnapPoints",
include_paths: ["platform/Length.h"],
typedom_types: ["Length", "Percent"],
typedom_types: ["Length", "Percentage"],
type_name: "Length",
converter: "ConvertLength",
direction_aware_options: {
......@@ -2282,7 +2282,7 @@
property_methods: ["ParseSingleValue"],
runtime_flag: "CSSScrollSnapPoints",
include_paths: ["platform/Length.h"],
typedom_types: ["Length", "Percent"],
typedom_types: ["Length", "Percentage"],
type_name: "Length",
converter: "ConvertLength",
direction_aware_options: {
......@@ -2297,7 +2297,7 @@
field_group: "*",
field_template: "<length>",
default_value: "Length()",
typedom_types: ["Length", "Percent"],
typedom_types: ["Length", "Percentage"],
converter: "ConvertLength",
},
{
......@@ -2305,7 +2305,7 @@
property_methods: ["ParseSingleValue"],
runtime_flag: "CSSScrollSnapPoints",
include_paths: ["platform/Length.h"],
typedom_types: ["Length", "Percent"],
typedom_types: ["Length", "Percentage"],
type_name: "Length",
converter: "ConvertLength",
direction_aware_options: {
......@@ -2318,7 +2318,7 @@
property_methods: ["ParseSingleValue"],
runtime_flag: "CSSScrollSnapPoints",
include_paths: ["platform/Length.h"],
typedom_types: ["Length", "Percent"],
typedom_types: ["Length", "Percentage"],
type_name: "Length",
converter: "ConvertLength",
direction_aware_options: {
......@@ -2333,7 +2333,7 @@
field_group: "*",
field_template: "<length>",
default_value: "Length()",
typedom_types: ["Length", "Percent"],
typedom_types: ["Length", "Percentage"],
converter: "ConvertLength",
},
{
......@@ -2343,7 +2343,7 @@
field_group: "*",
field_template: "<length>",
default_value: "Length()",
typedom_types: ["Length", "Percent"],
typedom_types: ["Length", "Percentage"],
converter: "ConvertLength",
},
{
......@@ -2353,7 +2353,7 @@
field_group: "*",
field_template: "<length>",
default_value: "Length()",
typedom_types: ["Length", "Percent"],
typedom_types: ["Length", "Percentage"],
converter: "ConvertLength",
},
{
......@@ -2709,7 +2709,7 @@
field_template: "<length>",
keywords: ["auto"],
default_value: "Length()",
typedom_types: ["Length", "Percent"],
typedom_types: ["Length", "Percentage"],
converter: "ConvertLengthOrAuto",
},
{
......@@ -2832,7 +2832,7 @@
interpolable: true,
custom_apply_functions_inherit: true,
custom_apply_functions_value: true,
typedom_types: ["Length", "Percent"],
typedom_types: ["Length", "Percentage"],
keywords: ["baseline", "sub", "super", "text-top", "text-bottom", "middle"],
},
{
......@@ -3445,7 +3445,7 @@
field_template: "<length>",
keywords: ["auto", "fit-content", "min-content", "max-content"],
default_value: "Length()",
typedom_types: ["Length", "Percent"],
typedom_types: ["Length", "Percentage"],
converter: "ConvertLengthSizing",
},
{
......
......@@ -22,11 +22,6 @@ class CORE_EXPORT CSSMathValue : public CSSNumericValue {
bool IsUnitValue() const final { return false; }
// From CSSStyleValue.
bool ContainsPercent() const final {
// TODO(776173): Implement
return false;
}
const CSSValue* ToCSSValue() const final;
protected:
......
......@@ -79,28 +79,4 @@ String CSSStyleValue::toString() const {
return result->CssText();
}
String CSSStyleValue::StyleValueTypeToString(StyleValueType type) {
switch (type) {
case StyleValueType::kNumberType:
return "number";
case StyleValueType::kPercentType:
return "percent";
case StyleValueType::kLengthType:
return "length";
case StyleValueType::kAngleType:
return "angle";
case StyleValueType::kTimeType:
return "time";
case StyleValueType::kFrequencyType:
return "frequency";
case StyleValueType::kResolutionType:
return "resolution";
case StyleValueType::kFlexType:
return "flex";
default:
NOTREACHED();
return "";
}
}
} // namespace blink
......@@ -28,28 +28,23 @@ class CORE_EXPORT CSSStyleValue : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
// This enum ordering is significant for CSSStyleValue::IsNumericValue.
enum StyleValueType {
kUnknownType,
kAngleType,
kFlexType,
kFrequencyType,
kInvertType,
kUnparsedType,
kKeywordType,
kLengthType,
kMaxType,
kMinType,
kNegateType,
kNumberType,
kPercentType,
kPositionType,
kProductType,
kResolutionType,
// Start of CSSNumericValue subclasses
kUnitType,
kSumType,
kTimeType,
kProductType,
kNegateType,
kInvertType,
kMinType,
kMaxType,
// End of CSSNumericValue subclasses
kTransformType,
kUnparsedType,
kPositionType,
kURLImageType,
kInvalidType,
};
static CSSStyleValue* parse(const ExecutionContext*,
......@@ -64,7 +59,9 @@ class CORE_EXPORT CSSStyleValue : public ScriptWrappable {
virtual ~CSSStyleValue() = default;
virtual StyleValueType GetType() const = 0;
virtual bool ContainsPercent() const { return false; }
bool IsNumericValue() const {
return GetType() >= kUnitType && GetType() <= kMaxType;
}
virtual const CSSValue* ToCSSValue() const = 0;
virtual const CSSValue* ToCSSValueWithProperty(CSSPropertyID) const {
......@@ -73,8 +70,6 @@ class CORE_EXPORT CSSStyleValue : public ScriptWrappable {
virtual String toString() const;
protected:
static String StyleValueTypeToString(StyleValueType);
CSSStyleValue() = default;
private:
......
......@@ -70,24 +70,7 @@ String CSSUnitValue::unit() const {
}
CSSStyleValue::StyleValueType CSSUnitValue::GetType() const {
if (unit_ == CSSPrimitiveValue::UnitType::kNumber)
return StyleValueType::kNumberType;
if (unit_ == CSSPrimitiveValue::UnitType::kPercentage)
return StyleValueType::kPercentType;
if (CSSPrimitiveValue::IsLength(unit_))
return StyleValueType::kLengthType;
if (CSSPrimitiveValue::IsAngle(unit_))
return StyleValueType::kAngleType;
if (CSSPrimitiveValue::IsTime(unit_))
return StyleValueType::kTimeType;
if (CSSPrimitiveValue::IsFrequency(unit_))
return StyleValueType::kFrequencyType;
if (CSSPrimitiveValue::IsResolution(unit_))
return StyleValueType::kResolutionType;
if (CSSPrimitiveValue::IsFlex(unit_))
return StyleValueType::kFlexType;
NOTREACHED();
return StyleValueType::kUnknownType;
return StyleValueType::kUnitType;
}
CSSUnitValue* CSSUnitValue::ConvertTo(
......
......@@ -45,10 +45,6 @@ class CORE_EXPORT CSSUnitValue final : public CSSNumericValue {
// From CSSStyleValue.
StyleValueType GetType() const final;
bool ContainsPercent() const final {
return unit_ == CSSPrimitiveValue::UnitType::kPercentage;
}
const CSSPrimitiveValue* ToCSSValue() const final;
CSSCalcExpressionNode* ToCalcExpressionNode() const final;
......
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