Skip to content

Commit f31adb8

Browse files
ericwilligersChromium LUCI CQ
authored andcommitted
CSS Transforms: scale() accepts percentages.
The functions scale() scaleX() scaleY() scaleZ() scale3d() and the property scale each accept percentages, that serialize as numbers. w3c/csswg-drafts#3399 w3c/csswg-drafts#4396 https://drafts.csswg.org/css-transforms-2/#transform-functions https://drafts.csswg.org/css-transforms-2/#propdef-scale Bug: 1179579 Change-Id: Icfbc42bf529c1c63045c3e918a6a1db2b14d1ae3 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2703674 Commit-Queue: Eric Willigers <[email protected]> Reviewed-by: Anders Hartvoll Ruud <[email protected]> Cr-Commit-Position: refs/heads/master@{#867008}
1 parent e0a000c commit f31adb8

File tree

10 files changed

+77
-77
lines changed

10 files changed

+77
-77
lines changed

third_party/blink/renderer/core/css/properties/css_parsing_utils.cc

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,22 @@ bool ConsumeNumbers(CSSParserTokenRange& args,
375375
return true;
376376
}
377377

378+
bool ConsumeNumbersOrPercents(CSSParserTokenRange& args,
379+
const CSSParserContext& context,
380+
CSSFunctionValue*& transform_value,
381+
unsigned number_of_arguments) {
382+
do {
383+
CSSValue* parsed_value =
384+
ConsumeNumberOrPercent(args, context, kValueRangeAll);
385+
if (!parsed_value)
386+
return false;
387+
transform_value->Append(*parsed_value);
388+
if (--number_of_arguments && !ConsumeCommaIncludingWhitespace(args))
389+
return false;
390+
} while (number_of_arguments);
391+
return true;
392+
}
393+
378394
bool ConsumePerspective(CSSParserTokenRange& args,
379395
const CSSParserContext& context,
380396
CSSFunctionValue*& transform_value,
@@ -841,20 +857,24 @@ CSSPrimitiveValue* ConsumePercent(CSSParserTokenRange& range,
841857
return nullptr;
842858
}
843859

844-
CSSPrimitiveValue* ConsumeAlphaValue(CSSParserTokenRange& range,
845-
const CSSParserContext& context) {
846-
if (CSSPrimitiveValue* value =
847-
ConsumeNumber(range, context, kValueRangeAll)) {
860+
CSSPrimitiveValue* ConsumeNumberOrPercent(CSSParserTokenRange& range,
861+
const CSSParserContext& context,
862+
ValueRange value_range) {
863+
if (CSSPrimitiveValue* value = ConsumeNumber(range, context, value_range)) {
848864
return value;
849865
}
850-
if (CSSPrimitiveValue* value =
851-
ConsumePercent(range, context, kValueRangeAll)) {
866+
if (CSSPrimitiveValue* value = ConsumePercent(range, context, value_range)) {
852867
return CSSNumericLiteralValue::Create(value->GetDoubleValue() / 100.0,
853868
CSSPrimitiveValue::UnitType::kNumber);
854869
}
855870
return nullptr;
856871
}
857872

873+
CSSPrimitiveValue* ConsumeAlphaValue(CSSParserTokenRange& range,
874+
const CSSParserContext& context) {
875+
return ConsumeNumberOrPercent(range, context, kValueRangeAll);
876+
}
877+
858878
bool CanConsumeCalcValue(CalculationCategory category,
859879
CSSParserMode css_parser_mode) {
860880
return category == kCalcLength || category == kCalcPercent ||
@@ -4706,13 +4726,13 @@ CSSValue* ConsumeTransformValue(CSSParserTokenRange& range,
47064726
case CSSValueID::kScaleY:
47074727
case CSSValueID::kScaleZ:
47084728
case CSSValueID::kScale:
4709-
parsed_value = ConsumeNumber(args, context, kValueRangeAll);
4729+
parsed_value = ConsumeNumberOrPercent(args, context, kValueRangeAll);
47104730
if (!parsed_value)
47114731
return nullptr;
47124732
if (function_id == CSSValueID::kScale &&
47134733
ConsumeCommaIncludingWhitespace(args)) {
47144734
transform_value->Append(*parsed_value);
4715-
parsed_value = ConsumeNumber(args, context, kValueRangeAll);
4735+
parsed_value = ConsumeNumberOrPercent(args, context, kValueRangeAll);
47164736
if (!parsed_value)
47174737
return nullptr;
47184738
}
@@ -4748,7 +4768,7 @@ CSSValue* ConsumeTransformValue(CSSParserTokenRange& range,
47484768
}
47494769
break;
47504770
case CSSValueID::kScale3d:
4751-
if (!ConsumeNumbers(args, context, transform_value, 3))
4771+
if (!ConsumeNumbersOrPercents(args, context, transform_value, 3))
47524772
return nullptr;
47534773
break;
47544774
case CSSValueID::kRotate3d:

third_party/blink/renderer/core/css/properties/css_parsing_utils.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,12 @@ CSSPrimitiveValue* ConsumeLength(CSSParserTokenRange&,
8888
CSSPrimitiveValue* ConsumePercent(CSSParserTokenRange&,
8989
const CSSParserContext&,
9090
ValueRange);
91+
92+
// Any percentages are converted to numbers.
93+
CSSPrimitiveValue* ConsumeNumberOrPercent(CSSParserTokenRange&,
94+
const CSSParserContext&,
95+
ValueRange);
96+
9197
CSSPrimitiveValue* ConsumeAlphaValue(CSSParserTokenRange&,
9298
const CSSParserContext&);
9399
CSSPrimitiveValue* ConsumeLengthOrPercent(

third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5635,24 +5635,23 @@ const CSSValue* Scale::ParseSingleValue(CSSParserTokenRange& range,
56355635
if (id == CSSValueID::kNone)
56365636
return css_parsing_utils::ConsumeIdent(range);
56375637

5638-
CSSValue* x_scale =
5639-
css_parsing_utils::ConsumeNumber(range, context, kValueRangeAll);
5638+
CSSPrimitiveValue* x_scale =
5639+
css_parsing_utils::ConsumeNumberOrPercent(range, context, kValueRangeAll);
56405640
if (!x_scale)
56415641
return nullptr;
56425642

56435643
CSSValueList* list = CSSValueList::CreateSpaceSeparated();
56445644
list->Append(*x_scale);
56455645

5646-
CSSValue* y_scale =
5647-
css_parsing_utils::ConsumeNumber(range, context, kValueRangeAll);
5646+
CSSPrimitiveValue* y_scale =
5647+
css_parsing_utils::ConsumeNumberOrPercent(range, context, kValueRangeAll);
56485648
if (y_scale) {
5649-
CSSValue* z_scale =
5650-
css_parsing_utils::ConsumeNumber(range, context, kValueRangeAll);
5649+
CSSPrimitiveValue* z_scale = css_parsing_utils::ConsumeNumberOrPercent(
5650+
range, context, kValueRangeAll);
56515651
if (z_scale) {
56525652
list->Append(*y_scale);
56535653
list->Append(*z_scale);
5654-
} else if (To<CSSPrimitiveValue>(x_scale)->GetDoubleValue() !=
5655-
To<CSSPrimitiveValue>(y_scale)->GetDoubleValue()) {
5654+
} else if (x_scale->GetDoubleValue() != y_scale->GetDoubleValue()) {
56565655
list->Append(*y_scale);
56575656
}
56585657
}
Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,25 @@
11
This is a testharness.js-based test.
22
PASS e.style['scale'] = "none" should set the property value
33
PASS e.style['scale'] = "1" should set the property value
4-
FAIL e.style['scale'] = "1%" should set the property value assert_not_equals: property should be set got disallowed value ""
4+
PASS e.style['scale'] = "1%" should set the property value
55
PASS e.style['scale'] = "100" should set the property value
6-
FAIL e.style['scale'] = "100%" should set the property value assert_not_equals: property should be set got disallowed value ""
6+
PASS e.style['scale'] = "100%" should set the property value
77
PASS e.style['scale'] = "100 100" should set the property value
8-
FAIL e.style['scale'] = "100% 100%" should set the property value assert_not_equals: property should be set got disallowed value ""
8+
PASS e.style['scale'] = "100% 100%" should set the property value
99
FAIL e.style['scale'] = "100 100 1" should set the property value assert_equals: serialization should be canonical expected "100" but got "100 100 1"
10-
FAIL e.style['scale'] = "100% 100% 1" should set the property value assert_not_equals: property should be set got disallowed value ""
10+
FAIL e.style['scale'] = "100% 100% 1" should set the property value assert_equals: serialization should be canonical expected "1" but got "1 1 1"
1111
PASS e.style['scale'] = "-100" should set the property value
12-
FAIL e.style['scale'] = "-100%" should set the property value assert_not_equals: property should be set got disallowed value ""
12+
PASS e.style['scale'] = "-100%" should set the property value
1313
PASS e.style['scale'] = "-100 -100" should set the property value
14-
FAIL e.style['scale'] = "-100% -100%" should set the property value assert_not_equals: property should be set got disallowed value ""
14+
PASS e.style['scale'] = "-100% -100%" should set the property value
1515
FAIL e.style['scale'] = "-100 -100 1" should set the property value assert_equals: serialization should be canonical expected "-100" but got "-100 -100 1"
16-
FAIL e.style['scale'] = "-100% -100% 1" should set the property value assert_not_equals: property should be set got disallowed value ""
16+
FAIL e.style['scale'] = "-100% -100% 1" should set the property value assert_equals: serialization should be canonical expected "-1" but got "-1 -1 1"
1717
PASS e.style['scale'] = "100 200" should set the property value
18-
FAIL e.style['scale'] = "100% 200%" should set the property value assert_not_equals: property should be set got disallowed value ""
18+
PASS e.style['scale'] = "100% 200%" should set the property value
1919
FAIL e.style['scale'] = "100 200 1" should set the property value assert_equals: serialization should be canonical expected "100 200" but got "100 200 1"
20-
FAIL e.style['scale'] = "100% 200% 1" should set the property value assert_not_equals: property should be set got disallowed value ""
20+
FAIL e.style['scale'] = "100% 200% 1" should set the property value assert_equals: serialization should be canonical expected "1 2" but got "1 2 1"
2121
PASS e.style['scale'] = "100 200 300" should set the property value
2222
PASS e.style['scale'] = "100 100 2" should set the property value
23+
PASS e.style['scale'] = "100% 200% 300%" should set the property value
2324
Harness: the test ran to completion.
2425

third_party/blink/web_tests/external/wpt/css/css-transforms/parsing/scale-parsing-valid.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
test_valid_value("scale", "100% 200% 1", "1 2");
3737
test_valid_value("scale", "100 200 300");
3838
test_valid_value("scale", "100 100 2", "100 100 2");
39-
39+
test_valid_value("scale", "100% 200% 300%", "1 2 3");
4040
</script>
4141
</body>
4242
</html>

third_party/blink/web_tests/external/wpt/css/css-transforms/parsing/transform-valid-expected.txt

Lines changed: 0 additions & 38 deletions
This file was deleted.

third_party/blink/web_tests/external/wpt/css/css-transforms/parsing/transform-valid.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232

3333
test_valid_value("transform", "scale(250%)", "scale(2.5)");
3434
test_valid_value("transform", "scale(325%, 475%)", "scale(3.25, 4.75)");
35+
test_valid_value("transform", "scale(1, 200%)", "scale(1, 2)");
3536

3637
test_valid_value("transform", "scale(-250%)", "scale(-2.5)");
3738
test_valid_value("transform", "scale(-500%, -620%)", "scale(-5, -6.2)");
@@ -42,11 +43,15 @@
4243
test_valid_value("transform", "scaleY(-8)");
4344
test_valid_value("transform", "scaleY(-85%)", "scaleY(-0.85)");
4445

46+
test_valid_value("transform", "scaleZ(4)");
47+
test_valid_value("transform", "scaleZ(25%)", "scaleZ(0.25)");
48+
4549
test_valid_value("transform", "scale3d(0.5, 2.5, 3)");
4650
test_valid_value("transform", "scale3d(50%, 250%, 300%)", "scale3d(0.5, 2.5, 3)");
4751

4852
test_valid_value("transform", "scale3d(-0.5, 2.5, -3)");
4953
test_valid_value("transform", "scale3d(-50%, 250%, -300%)", "scale3d(-0.5, 2.5, -3)");
54+
test_valid_value("transform", "scale3d(1, 200%, 3)", "scale3d(1, 2, 3)");
5055

5156
test_valid_value("transform", "rotate(0)", "rotate(0deg)");
5257
test_valid_value("transform", "rotate(90deg)");

third_party/blink/web_tests/transforms/scale-parsing.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,19 @@
1515
expect('5 5').parsesAs('5').isComputedTo('5');
1616
expect('1 -2.3').parsesAs('1 -2.3').isComputedTo('1 -2.3');
1717
expect('1 -2.3 4').parsesAs('1 -2.3 4').isComputedTo('1 -2.3 4');
18+
expect('30%').parsesAs('0.3').isComputedTo('0.3');
1819

1920
expect('calc(1 * 2)').parsesAs('2').isComputedTo('2');
2021
expect('calc(1 * 2) calc(2 / 4)').parsesAs('2 0.5').isComputedTo('2 0.5');
2122
expect('calc(1 * 2) calc(2 / 4) calc(0.5)').parsesAs('2 0.5 0.5').isComputedTo('2 0.5 0.5');
23+
expect('calc(1 * 2) calc(2 / 4) calc(0.5%)').parsesAs('2 0.5 0.005').isComputedTo('2 0.5 0.005');
2224

2325
expect('2px').isInvalid();
24-
expect('30%').isInvalid();
2526
expect('1 1 1 1').isInvalid();
2627
expect('1 2 3deg').isInvalid();
2728
expect('1 + 1').isInvalid();
2829
expect('1,').isInvalid();
2930
expect('1, 2,').isInvalid();
3031
expect('calc(1 * 2 + 4px) calc(2 / 4) calc(0.5)').isInvalid();
3132
expect('calc(1 * 2) calc(2 / 4 * 4deg) calc(0.5)').isInvalid();
32-
expect('calc(1 * 2) calc(2 / 4) calc(0.5%)').isInvalid();
3333
</script>

third_party/blink/web_tests/transforms/transform-parsing-expected.txt

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,23 +40,26 @@ PASS "transform: translateY(1px, 2px);" should be invalid
4040
PASS "transform: scale(1);" should parse as "scale(1)"
4141
PASS "transform: scale(2, 3);" should parse as "scale(2, 3)"
4242
PASS "transform: scale(2, 3);" should be computed to "matrix(2, 0, 0, 3, 0, 0)"
43+
PASS "transform: scale(20%, 50%);" should parse as "scale(0.2, 0.5)"
44+
PASS "transform: scale(20%, 50%);" should be computed to "matrix(0.2, 0, 0, 0.5, 0, 0)"
4345
PASS "transform: scale();" should be invalid
4446
PASS "transform: scale(1,);" should be invalid
4547
PASS "transform: scale(1, 2, 3);" should be invalid
4648
PASS "transform: scale(1px, 2px);" should be invalid
47-
PASS "transform: scale(20%, 50%);" should be invalid
4849
PASS "transform: scaleX(2);" should parse as "scaleX(2)"
4950
PASS "transform: scaleX(2);" should be computed to "matrix(2, 0, 0, 1, 0, 0)"
51+
PASS "transform: scaleX(50%);" should parse as "scaleX(0.5)"
52+
PASS "transform: scaleX(50%);" should be computed to "matrix(0.5, 0, 0, 1, 0, 0)"
5053
PASS "transform: scaleX();" should be invalid
5154
PASS "transform: scaleX(1, 2);" should be invalid
5255
PASS "transform: scaleX(1px);" should be invalid
53-
PASS "transform: scaleX(50%);" should be invalid
5456
PASS "transform: scaleY(2);" should parse as "scaleY(2)"
5557
PASS "transform: scaleY(2);" should be computed to "matrix(1, 0, 0, 2, 0, 0)"
58+
PASS "transform: scaleY(50%);" should parse as "scaleY(0.5)"
59+
PASS "transform: scaleY(50%);" should be computed to "matrix(1, 0, 0, 0.5, 0, 0)"
5660
PASS "transform: scaleY();" should be invalid
5761
PASS "transform: scaleY(1, 2);" should be invalid
5862
PASS "transform: scaleY(1px);" should be invalid
59-
PASS "transform: scaleY(50%);" should be invalid
6063
PASS "transform: rotate(0);" should parse as "rotate(0deg)"
6164
PASS "transform: rotate(1deg);" should parse as "rotate(1deg)"
6265
PASS "transform: rotate(2grad);" should parse as "rotate(2grad)"
@@ -113,16 +116,18 @@ PASS "transform: translateZ(50%);" should be invalid
113116
PASS "transform: translateZ(1px, 2px);" should be invalid
114117
PASS "transform: scale3d(2, 3, 4);" should parse as "scale3d(2, 3, 4)"
115118
PASS "transform: scale3d(2, 3, 4);" should be computed to "matrix3d(2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 4, 0, 0, 0, 0, 1)"
119+
PASS "transform: scale3d(20%, 50%, 60%);" should parse as "scale3d(0.2, 0.5, 0.6)"
120+
PASS "transform: scale3d(20%, 50%, 60%);" should be computed to "matrix3d(0.2, 0, 0, 0, 0, 0.5, 0, 0, 0, 0, 0.6, 0, 0, 0, 0, 1)"
116121
PASS "transform: scale3d();" should be invalid
117122
PASS "transform: scale3d(1, 2, 3, 4);" should be invalid
118123
PASS "transform: scale3d(1px, 2px, 3px);" should be invalid
119-
PASS "transform: scale3d(20%, 50%, 60%);" should be invalid
120124
PASS "transform: scaleZ(2);" should parse as "scaleZ(2)"
121125
PASS "transform: scaleZ(2);" should be computed to "matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1)"
126+
PASS "transform: scaleZ(50%);" should parse as "scaleZ(0.5)"
127+
PASS "transform: scaleZ(50%);" should be computed to "matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0.5, 0, 0, 0, 0, 1)"
122128
PASS "transform: scaleZ();" should be invalid
123129
PASS "transform: scaleZ(1, 2);" should be invalid
124130
PASS "transform: scaleZ(1px);" should be invalid
125-
PASS "transform: scaleZ(50%);" should be invalid
126131
PASS "transform: rotate3d(0, 0, 0, 0);" should parse as "rotate3d(0, 0, 0, 0deg)"
127132
PASS "transform: rotate3d(1, 2, 3, 4deg);" should parse as "rotate3d(1, 2, 3, 4deg)"
128133
PASS "transform: rotate3d();" should be invalid

third_party/blink/web_tests/transforms/transform-parsing.html

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,25 +54,25 @@
5454
// scale()
5555
expect('scale(1)').parsesAs('scale(1)');
5656
expect('scale(2, 3)').parsesAs('scale(2, 3)').isComputedTo('matrix(2, 0, 0, 3, 0, 0)');
57+
expect('scale(20%, 50%)').parsesAs('scale(0.2, 0.5)').isComputedTo('matrix(0.2, 0, 0, 0.5, 0, 0)');
5758
expect('scale()').isInvalid();
5859
expect('scale(1,)').isInvalid();
5960
expect('scale(1, 2, 3)').isInvalid();
6061
expect('scale(1px, 2px)').isInvalid();
61-
expect('scale(20%, 50%)').isInvalid();
6262

6363
// scaleX()
6464
expect('scaleX(2)').parsesAs('scaleX(2)').isComputedTo('matrix(2, 0, 0, 1, 0, 0)');
65+
expect('scaleX(50%)').parsesAs('scaleX(0.5)').isComputedTo('matrix(0.5, 0, 0, 1, 0, 0)');
6566
expect('scaleX()').isInvalid();
6667
expect('scaleX(1, 2)').isInvalid();
6768
expect('scaleX(1px)').isInvalid();
68-
expect('scaleX(50%)').isInvalid();
6969

7070
// scaleY()
7171
expect('scaleY(2)').parsesAs('scaleY(2)').isComputedTo('matrix(1, 0, 0, 2, 0, 0)');
72+
expect('scaleY(50%)').parsesAs('scaleY(0.5)').isComputedTo('matrix(1, 0, 0, 0.5, 0, 0)');
7273
expect('scaleY()').isInvalid();
7374
expect('scaleY(1, 2)').isInvalid();
7475
expect('scaleY(1px)').isInvalid();
75-
expect('scaleY(50%)').isInvalid();
7676

7777
// rotate()
7878
expect('rotate(0)').parsesAs('rotate(0deg)');
@@ -146,18 +146,20 @@
146146
// scale3d()
147147
expect('scale3d(2, 3, 4)').parsesAs('scale3d(2, 3, 4)').
148148
isComputedTo('matrix3d(2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 4, 0, 0, 0, 0, 1)');
149+
expect('scale3d(20%, 50%, 60%)').parsesAs('scale3d(0.2, 0.5, 0.6)').
150+
isComputedTo('matrix3d(0.2, 0, 0, 0, 0, 0.5, 0, 0, 0, 0, 0.6, 0, 0, 0, 0, 1)');
149151
expect('scale3d()').isInvalid();
150152
expect('scale3d(1, 2, 3, 4)').isInvalid();
151153
expect('scale3d(1px, 2px, 3px)').isInvalid();
152-
expect('scale3d(20%, 50%, 60%)').isInvalid();
153154

154155
// scaleZ()
155156
expect('scaleZ(2)').parsesAs('scaleZ(2)').
156157
isComputedTo('matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1)');
158+
expect('scaleZ(50%)').parsesAs('scaleZ(0.5)').
159+
isComputedTo('matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0.5, 0, 0, 0, 0, 1)');
157160
expect('scaleZ()').isInvalid();
158161
expect('scaleZ(1, 2)').isInvalid();
159162
expect('scaleZ(1px)').isInvalid();
160-
expect('scaleZ(50%)').isInvalid();
161163

162164
// rotate3d()
163165
expect('rotate3d(0, 0, 0, 0)').parsesAs('rotate3d(0, 0, 0, 0deg)');

0 commit comments

Comments
 (0)