summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp118
-rw-r--r--Userland/Libraries/LibWeb/CSS/Parser/Parser.h1
-rw-r--r--Userland/Libraries/LibWeb/CSS/Properties.json17
3 files changed, 136 insertions, 0 deletions
diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp
index 6076cb410d..d9c6ca7beb 100644
--- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp
+++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp
@@ -3989,6 +3989,120 @@ RefPtr<StyleValue> Parser::parse_transform_value(Vector<StyleComponentValueRule>
return StyleValueList::create(move(transformations), StyleValueList::Separator::Space);
}
+// https://www.w3.org/TR/css-transforms-1/#propdef-transform-origin
+// FIXME: This only supports a 2D position
+RefPtr<StyleValue> Parser::parse_transform_origin_value(Vector<StyleComponentValueRule> const& component_values)
+{
+ enum class Axis {
+ None,
+ X,
+ Y,
+ };
+
+ struct AxisOffset {
+ Axis axis;
+ NonnullRefPtr<StyleValue> offset;
+ };
+
+ auto to_axis_offset = [](RefPtr<StyleValue> value) -> Optional<AxisOffset> {
+ if (value->is_percentage())
+ return AxisOffset { Axis::None, value->as_percentage() };
+ if (value->is_length())
+ return AxisOffset { Axis::None, value->as_length() };
+ if (value->has_length())
+ return AxisOffset { Axis::None, LengthStyleValue::create(value->to_length()) };
+ if (value->is_identifier()) {
+ switch (value->to_identifier()) {
+ case ValueID::Top:
+ return AxisOffset { Axis::Y, PercentageStyleValue::create(Percentage(0)) };
+ case ValueID::Left:
+ return AxisOffset { Axis::X, PercentageStyleValue::create(Percentage(0)) };
+ case ValueID::Center:
+ return AxisOffset { Axis::None, PercentageStyleValue::create(Percentage(50)) };
+ case ValueID::Bottom:
+ return AxisOffset { Axis::Y, PercentageStyleValue::create(Percentage(100)) };
+ case ValueID::Right:
+ return AxisOffset { Axis::X, PercentageStyleValue::create(Percentage(100)) };
+ default:
+ return {};
+ }
+ }
+ return {};
+ };
+
+ auto make_list = [](NonnullRefPtr<StyleValue> x_value, NonnullRefPtr<StyleValue> y_value) -> NonnullRefPtr<StyleValueList> {
+ NonnullRefPtrVector<StyleValue> values;
+ values.append(x_value);
+ values.append(y_value);
+ return StyleValueList::create(move(values), StyleValueList::Separator::Space);
+ };
+
+ switch (component_values.size()) {
+ case 1: {
+ auto single_value = to_axis_offset(parse_css_value(component_values[0]));
+ if (!single_value.has_value())
+ return nullptr;
+ // If only one value is specified, the second value is assumed to be center.
+ // FIXME: If one or two values are specified, the third value is assumed to be 0px.
+ switch (single_value->axis) {
+ case Axis::None:
+ case Axis::X:
+ return make_list(single_value->offset, PercentageStyleValue::create(Percentage(50)));
+ case Axis::Y:
+ return make_list(PercentageStyleValue::create(Percentage(50)), single_value->offset);
+ }
+ VERIFY_NOT_REACHED();
+ }
+ case 2: {
+ auto first_value = to_axis_offset(parse_css_value(component_values[0]));
+ auto second_value = to_axis_offset(parse_css_value(component_values[1]));
+ if (!first_value.has_value() || !second_value.has_value())
+ return nullptr;
+
+ RefPtr<StyleValue> x_value;
+ RefPtr<StyleValue> y_value;
+
+ if (first_value->axis == Axis::X) {
+ x_value = first_value->offset;
+ } else if (first_value->axis == Axis::Y) {
+ y_value = first_value->offset;
+ }
+
+ if (second_value->axis == Axis::X) {
+ if (x_value)
+ return nullptr;
+ x_value = second_value->offset;
+ // Put the other in Y since its axis can't have been X
+ y_value = first_value->offset;
+ } else if (second_value->axis == Axis::Y) {
+ if (y_value)
+ return nullptr;
+ y_value = second_value->offset;
+ // Put the other in X since its axis can't have been Y
+ x_value = first_value->offset;
+ } else {
+ if (x_value) {
+ VERIFY(!y_value);
+ y_value = second_value->offset;
+ } else {
+ VERIFY(!x_value);
+ x_value = second_value->offset;
+ }
+ }
+ // If two or more values are defined and either no value is a keyword, or the only used keyword is center,
+ // then the first value represents the horizontal position (or offset) and the second represents the vertical position (or offset).
+ // FIXME: A third value always represents the Z position (or offset) and must be of type <length>.
+ if (first_value->axis == Axis::None && second_value->axis == Axis::None) {
+ x_value = first_value->offset;
+ y_value = second_value->offset;
+ }
+ return make_list(x_value.release_nonnull(), y_value.release_nonnull());
+ }
+ }
+
+ return nullptr;
+}
+
RefPtr<StyleValue> Parser::parse_as_css_value(PropertyID property_id)
{
auto component_values = parse_as_list_of_component_values();
@@ -4136,6 +4250,10 @@ Result<NonnullRefPtr<StyleValue>, Parser::ParsingResult> Parser::parse_css_value
if (auto parsed_value = parse_transform_value(component_values))
return parsed_value.release_nonnull();
return ParsingResult::SyntaxError;
+ case PropertyID::TransformOrigin:
+ if (auto parse_value = parse_transform_origin_value(component_values))
+ return parse_value.release_nonnull();
+ return ParsingResult ::SyntaxError;
default:
break;
}
diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h
index 06d64b1abe..d7e403ef9b 100644
--- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h
+++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h
@@ -298,6 +298,7 @@ private:
RefPtr<StyleValue> parse_overflow_value(Vector<StyleComponentValueRule> const&);
RefPtr<StyleValue> parse_text_decoration_value(Vector<StyleComponentValueRule> const&);
RefPtr<StyleValue> parse_transform_value(Vector<StyleComponentValueRule> const&);
+ RefPtr<StyleValue> parse_transform_origin_value(Vector<StyleComponentValueRule> const&);
// calc() parsing, according to https://www.w3.org/TR/css-values-3/#calc-syntax
OwnPtr<CalculatedStyleValue::CalcSum> parse_calc_sum(TokenStream<StyleComponentValueRule>&);
diff --git a/Userland/Libraries/LibWeb/CSS/Properties.json b/Userland/Libraries/LibWeb/CSS/Properties.json
index 7d120038a4..f3e0e947fc 100644
--- a/Userland/Libraries/LibWeb/CSS/Properties.json
+++ b/Userland/Libraries/LibWeb/CSS/Properties.json
@@ -1371,6 +1371,23 @@
"inherited": false,
"initial": "none"
},
+ "transform-origin": {
+ "affects-layout": false,
+ "inherited": false,
+ "initial": "50% 50%",
+ "max-values": 3,
+ "valid-types": [
+ "length",
+ "percentage"
+ ],
+ "valid-identifiers": [
+ "bottom",
+ "center",
+ "left",
+ "right",
+ "top"
+ ]
+ },
"user-select": {
"affects-layout": false,
"inherited": false,