@@ -2199,61 +2199,62 @@ RefPtr<StyleValue const> Parser::parse_shape_outside_value(TokenStream<Component
21992199 return StyleValueList::create ({ basic_shape_value.release_nonnull (), shape_box_value.release_nonnull () }, StyleValueList::Separator::Space);
22002200}
22012201
2202+ // https://drafts.csswg.org/css-transforms-2/#propdef-rotate
22022203RefPtr<StyleValue const > Parser::parse_rotate_value (TokenStream<ComponentValue>& tokens)
22032204{
2204- // Value: none | <angle> | [ x | y | z | <number>{3} ] && <angle>
2205+ // none | <angle> | [ x | y | z | <number>{3} ] && <angle>
22052206
2206- if (tokens.remaining_token_count () == 1 ) {
2207- // "none"
2208- if (auto none = parse_all_as_single_keyword_value (tokens, Keyword::None))
2209- return none;
2207+ // none
2208+ if (auto none = parse_all_as_single_keyword_value (tokens, Keyword::None))
2209+ return none;
2210+
2211+ auto transaction = tokens.begin_transaction ();
2212+
2213+ auto angle = parse_angle_value (tokens);
2214+ tokens.discard_whitespace ();
22102215
2211- // <angle>
2212- if (auto angle = parse_angle_value (tokens))
2213- return TransformationStyleValue::create (PropertyID::Rotate, TransformFunction::Rotate, { angle.release_nonnull () });
2216+ // <angle>
2217+ if (angle && !tokens.has_next_token ()) {
2218+ transaction.commit ();
2219+ return TransformationStyleValue::create (PropertyID::Rotate, TransformFunction::Rotate, { angle.release_nonnull () });
22142220 }
22152221
22162222 auto parse_one_of_xyz = [&]() -> Optional<ComponentValue const &> {
2217- auto transaction = tokens.begin_transaction ();
2223+ auto xyz_transaction = tokens.begin_transaction ();
2224+ tokens.discard_whitespace ();
22182225 auto const & axis = tokens.consume_a_token ();
22192226
22202227 if (axis.is_ident (" x" sv) || axis.is_ident (" y" sv) || axis.is_ident (" z" sv)) {
2221- transaction .commit ();
2228+ xyz_transaction .commit ();
22222229 return axis;
22232230 }
22242231
22252232 return {};
22262233 };
22272234
22282235 // [ x | y | z ] && <angle>
2229- if (tokens.remaining_token_count () == 2 ) {
2230- // Try parsing `x <angle>`
2231- if (auto axis = parse_one_of_xyz (); axis.has_value ()) {
2232- if (auto angle = parse_angle_value (tokens); angle) {
2233- if (axis->is_ident (" x" sv))
2234- return TransformationStyleValue::create (PropertyID::Rotate, TransformFunction::RotateX, { angle.release_nonnull () });
2235- if (axis->is_ident (" y" sv))
2236- return TransformationStyleValue::create (PropertyID::Rotate, TransformFunction::RotateY, { angle.release_nonnull () });
2237- if (axis->is_ident (" z" sv))
2238- return TransformationStyleValue::create (PropertyID::Rotate, TransformFunction::RotateZ, { angle.release_nonnull () });
2239- }
2240- }
2236+ if (auto axis = parse_one_of_xyz (); axis.has_value ()) {
2237+ tokens.discard_whitespace ();
22412238
2242- // Try parsing `<angle> x`
2243- if (auto angle = parse_angle_value (tokens); angle) {
2244- if (auto axis = parse_one_of_xyz (); axis.has_value ()) {
2245- if (axis->is_ident (" x" sv))
2246- return TransformationStyleValue::create (PropertyID::Rotate, TransformFunction::RotateX, { angle.release_nonnull () });
2247- if (axis->is_ident (" y" sv))
2248- return TransformationStyleValue::create (PropertyID::Rotate, TransformFunction::RotateY, { angle.release_nonnull () });
2249- if (axis->is_ident (" z" sv))
2250- return TransformationStyleValue::create (PropertyID::Rotate, TransformFunction::RotateZ, { angle.release_nonnull () });
2251- }
2239+ if (!angle)
2240+ angle = parse_angle_value (tokens);
2241+
2242+ if (angle) {
2243+ transaction.commit ();
2244+ if (axis->is_ident (" x" sv))
2245+ return TransformationStyleValue::create (PropertyID::Rotate, TransformFunction::RotateX, { angle.release_nonnull () });
2246+ if (axis->is_ident (" y" sv))
2247+ return TransformationStyleValue::create (PropertyID::Rotate, TransformFunction::RotateY, { angle.release_nonnull () });
2248+ if (axis->is_ident (" z" sv))
2249+ return TransformationStyleValue::create (PropertyID::Rotate, TransformFunction::RotateZ, { angle.release_nonnull () });
2250+ VERIFY_NOT_REACHED ();
22522251 }
2252+
2253+ return nullptr ;
22532254 }
22542255
22552256 auto parse_three_numbers = [&]() -> Optional<StyleValueVector> {
2256- auto transaction = tokens.begin_transaction ();
2257+ auto numbers_transaction = tokens.begin_transaction ();
22572258 StyleValueVector numbers;
22582259 for (size_t i = 0 ; i < 3 ; ++i) {
22592260 if (auto number = parse_number_value (tokens); number) {
@@ -2262,27 +2263,24 @@ RefPtr<StyleValue const> Parser::parse_rotate_value(TokenStream<ComponentValue>&
22622263 return {};
22632264 }
22642265 }
2265- transaction .commit ();
2266+ numbers_transaction .commit ();
22662267 return numbers;
22672268 };
22682269
22692270 // <number>{3} && <angle>
2270- if (tokens.remaining_token_count () == 4 ) {
2271- // Try parsing <number>{3} <angle>
2272- if (auto maybe_numbers = parse_three_numbers (); maybe_numbers.has_value ()) {
2273- if (auto angle = parse_angle_value (tokens); angle) {
2274- auto numbers = maybe_numbers.release_value ();
2275- return TransformationStyleValue::create (PropertyID::Rotate, TransformFunction::Rotate3d, { numbers[0 ], numbers[1 ], numbers[2 ], angle.release_nonnull () });
2276- }
2277- }
2271+ if (auto maybe_numbers = parse_three_numbers (); maybe_numbers.has_value ()) {
2272+ tokens.discard_whitespace ();
22782273
2279- // Try parsing <angle> <number>{3}
2280- if (auto angle = parse_angle_value (tokens); angle) {
2281- if (auto maybe_numbers = parse_three_numbers (); maybe_numbers.has_value ()) {
2282- auto numbers = maybe_numbers.release_value ();
2283- return TransformationStyleValue::create (PropertyID::Rotate, TransformFunction::Rotate3d, { numbers[0 ], numbers[1 ], numbers[2 ], angle.release_nonnull () });
2284- }
2274+ if (!angle)
2275+ angle = parse_angle_value (tokens);
2276+
2277+ if (angle) {
2278+ auto numbers = maybe_numbers.release_value ();
2279+ transaction.commit ();
2280+ return TransformationStyleValue::create (PropertyID::Rotate, TransformFunction::Rotate3d, { numbers[0 ], numbers[1 ], numbers[2 ], angle.release_nonnull () });
22852281 }
2282+
2283+ return nullptr ;
22862284 }
22872285
22882286 return nullptr ;
@@ -4834,6 +4832,13 @@ RefPtr<StyleValue const> Parser::parse_touch_action_value(TokenStream<ComponentV
48344832// https://www.w3.org/TR/css-transforms-1/#propdef-transform-origin
48354833RefPtr<StyleValue const > Parser::parse_transform_origin_value (TokenStream<ComponentValue>& tokens)
48364834{
4835+ // [ left | center | right | top | bottom | <length-percentage> ]
4836+ // |
4837+ // [ left | center | right | <length-percentage> ]
4838+ // [ top | center | bottom | <length-percentage> ] <length>?
4839+ // |
4840+ // [[ center | left | right ] && [ center | top | bottom ]] <length>?
4841+
48374842 enum class Axis {
48384843 None,
48394844 X,
@@ -4875,34 +4880,31 @@ RefPtr<StyleValue const> Parser::parse_transform_origin_value(TokenStream<Compon
48754880 };
48764881
48774882 auto transaction = tokens.begin_transaction ();
4883+ tokens.discard_whitespace ();
48784884
48794885 auto make_list = [&transaction](NonnullRefPtr<StyleValue const > const & x_value, NonnullRefPtr<StyleValue const > const & y_value, NonnullRefPtr<StyleValue const > const & z_value) -> NonnullRefPtr<StyleValueList> {
48804886 transaction.commit ();
48814887 return StyleValueList::create (StyleValueVector { x_value, y_value, z_value }, StyleValueList::Separator::Space);
48824888 };
48834889
4884- static StyleValue const & zero_value = LengthStyleValue::create (Length::make_px (0 ));
4890+ NonnullRefPtr< StyleValue const > const zero_value = LengthStyleValue::create (Length::make_px (0 ));
48854891
4886- if (tokens.remaining_token_count () == 1 ) {
4887- auto single_value = to_axis_offset (parse_css_value_for_property (PropertyID::TransformOrigin, tokens));
4888- if (!single_value.has_value ())
4889- return nullptr ;
4892+ auto first_value = to_axis_offset (parse_css_value_for_property (PropertyID::TransformOrigin, tokens));
4893+ if (!first_value.has_value ())
4894+ return nullptr ;
4895+ tokens.discard_whitespace ();
4896+ if (!tokens.has_next_token ()) {
48904897 // If only one value is specified, the second value is assumed to be center.
4891- // FIXME: If one or two values are specified, the third value is assumed to be 0px.
4892- switch (single_value->axis ) {
4898+ switch (first_value->axis ) {
48934899 case Axis::None:
48944900 case Axis::X:
4895- return make_list (single_value ->offset , KeywordStyleValue::create (Keyword::Center), zero_value);
4901+ return make_list (first_value ->offset , KeywordStyleValue::create (Keyword::Center), zero_value);
48964902 case Axis::Y:
4897- return make_list (KeywordStyleValue::create (Keyword::Center), single_value ->offset , zero_value);
4903+ return make_list (KeywordStyleValue::create (Keyword::Center), first_value ->offset , zero_value);
48984904 }
48994905 VERIFY_NOT_REACHED ();
49004906 }
49014907
4902- if (tokens.remaining_token_count () > 3 )
4903- return nullptr ;
4904-
4905- auto first_value = to_axis_offset (parse_css_value_for_property (PropertyID::TransformOrigin, tokens));
49064908 auto second_value = to_axis_offset (parse_css_value_for_property (PropertyID::TransformOrigin, tokens));
49074909 auto third_value = parse_length_value (tokens);
49084910
@@ -5040,20 +5042,23 @@ RefPtr<StyleValue const> Parser::parse_transition_property_value(TokenStream<Com
50405042 return StyleValueList::create (move (transition_properties), StyleValueList::Separator::Comma);
50415043}
50425044
5045+ // https://drafts.csswg.org/css-transforms-2/#propdef-translate
50435046RefPtr<StyleValue const > Parser::parse_translate_value (TokenStream<ComponentValue>& tokens)
50445047{
5045- if (tokens. remaining_token_count () == 1 ) {
5046- // "none"
5047- if ( auto none = parse_all_as_single_keyword_value (tokens, Keyword::None))
5048- return none;
5049- }
5048+ // none | <length-percentage> [ <length-percentage> <length>? ]?
5049+
5050+ // none
5051+ if ( auto none = parse_all_as_single_keyword_value (tokens, Keyword::None))
5052+ return none;
50505053
50515054 auto transaction = tokens.begin_transaction ();
50525055
5056+ // <length-percentage> [ <length-percentage> <length>? ]?
50535057 auto maybe_x = parse_length_percentage_value (tokens);
50545058 if (!maybe_x)
50555059 return nullptr ;
50565060
5061+ tokens.discard_whitespace ();
50575062 if (!tokens.has_next_token ()) {
50585063 transaction.commit ();
50595064 return TransformationStyleValue::create (PropertyID::Translate, TransformFunction::Translate, { maybe_x.release_nonnull (), LengthStyleValue::create (Length::make_px (0 )) });
@@ -5063,6 +5068,7 @@ RefPtr<StyleValue const> Parser::parse_translate_value(TokenStream<ComponentValu
50635068 if (!maybe_y)
50645069 return nullptr ;
50655070
5071+ tokens.discard_whitespace ();
50665072 if (!tokens.has_next_token ()) {
50675073 transaction.commit ();
50685074 return TransformationStyleValue::create (PropertyID::Translate, TransformFunction::Translate, { maybe_x.release_nonnull (), maybe_y.release_nonnull () });
@@ -5077,20 +5083,23 @@ RefPtr<StyleValue const> Parser::parse_translate_value(TokenStream<ComponentValu
50775083 return TransformationStyleValue::create (PropertyID::Translate, TransformFunction::Translate3d, { maybe_x.release_nonnull (), maybe_y.release_nonnull (), maybe_z.release_nonnull () });
50785084}
50795085
5086+ // https://drafts.csswg.org/css-transforms-2/#propdef-scale
50805087RefPtr<StyleValue const > Parser::parse_scale_value (TokenStream<ComponentValue>& tokens)
50815088{
5082- if (tokens. remaining_token_count () == 1 ) {
5083- // "none"
5084- if ( auto none = parse_all_as_single_keyword_value (tokens, Keyword::None))
5085- return none;
5086- }
5089+ // none | [ <number> | <percentage> ]{1,3}
5090+
5091+ // none
5092+ if ( auto none = parse_all_as_single_keyword_value (tokens, Keyword::None))
5093+ return none;
50875094
50885095 auto transaction = tokens.begin_transaction ();
50895096
5097+ // [ <number> | <percentage> ]{1,3}
50905098 auto maybe_x = parse_number_percentage_value (tokens);
50915099 if (!maybe_x)
50925100 return nullptr ;
50935101
5102+ tokens.discard_whitespace ();
50945103 if (!tokens.has_next_token ()) {
50955104 transaction.commit ();
50965105 return TransformationStyleValue::create (PropertyID::Scale, TransformFunction::Scale, { *maybe_x, *maybe_x });
@@ -5100,6 +5109,7 @@ RefPtr<StyleValue const> Parser::parse_scale_value(TokenStream<ComponentValue>&
51005109 if (!maybe_y)
51015110 return nullptr ;
51025111
5112+ tokens.discard_whitespace ();
51035113 if (!tokens.has_next_token ()) {
51045114 transaction.commit ();
51055115 return TransformationStyleValue::create (PropertyID::Scale, TransformFunction::Scale, { maybe_x.release_nonnull (), maybe_y.release_nonnull () });
0 commit comments