1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 19:07:35 +00:00

LibWeb: Support transform: translate(...) by percentage

This commit is contained in:
Simon Wanner 2022-03-21 23:18:38 +01:00 committed by Andreas Kling
parent bc5d39493b
commit dc94879b83
4 changed files with 43 additions and 32 deletions

View file

@ -72,7 +72,7 @@ public:
struct Transformation { struct Transformation {
CSS::TransformFunction function; CSS::TransformFunction function;
Vector<Variant<CSS::Length, float>> values; Vector<Variant<CSS::LengthPercentage, float>> values;
}; };
struct TransformOrigin { struct TransformOrigin {

View file

@ -3976,6 +3976,11 @@ RefPtr<StyleValue> Parser::parse_transform_value(Vector<StyleComponentValueRule>
} else if (value.is(Token::Type::Number)) { } else if (value.is(Token::Type::Number)) {
auto number = parse_numeric_value(value); auto number = parse_numeric_value(value);
values.append(number.release_nonnull()); values.append(number.release_nonnull());
} else if (value.is(Token::Type::Percentage)) {
auto percentage = parse_dimension_value(value);
if (!percentage || !percentage->is_percentage())
return nullptr;
values.append(percentage.release_nonnull());
} else { } else {
dbgln_if(CSS_PARSER_DEBUG, "FIXME: Unsupported value type for transformation!"); dbgln_if(CSS_PARSER_DEBUG, "FIXME: Unsupported value type for transformation!");
return nullptr; return nullptr;

View file

@ -329,10 +329,12 @@ Vector<CSS::Transformation> StyleProperties::transformations() const
auto& transformation_style_value = it.as_transformation(); auto& transformation_style_value = it.as_transformation();
CSS::Transformation transformation; CSS::Transformation transformation;
transformation.function = transformation_style_value.transform_function(); transformation.function = transformation_style_value.transform_function();
Vector<Variant<CSS::Length, float>> values; Vector<Variant<CSS::LengthPercentage, float>> values;
for (auto& transformation_value : transformation_style_value.values()) { for (auto& transformation_value : transformation_style_value.values()) {
if (transformation_value.is_length()) { if (transformation_value.is_length()) {
values.append({ transformation_value.to_length() }); values.append({ transformation_value.to_length() });
} else if (transformation_value.is_percentage()) {
values.append({ transformation_value.as_percentage().percentage() });
} else if (transformation_value.is_numeric()) { } else if (transformation_value.is_numeric()) {
values.append({ transformation_value.to_number() }); values.append({ transformation_value.to_number() });
} else if (transformation_value.is_angle()) { } else if (transformation_value.is_angle()) {

View file

@ -143,74 +143,78 @@ void StackingContext::paint_internal(PaintContext& context) const
Gfx::FloatMatrix4x4 StackingContext::get_transformation_matrix(CSS::Transformation const& transformation) const Gfx::FloatMatrix4x4 StackingContext::get_transformation_matrix(CSS::Transformation const& transformation) const
{ {
Vector<float> float_values; auto count = transformation.values.size();
for (auto const& value : transformation.values) { auto value = [this, transformation](size_t index, CSS::Length& reference) -> float {
value.visit( return transformation.values[index].visit(
[&](CSS::Length const& value) { [this, reference](CSS::LengthPercentage const& value) {
float_values.append(value.to_px(m_box)); return value.resolved(m_box, reference).to_px(m_box);
}, },
[&](float value) { [](float value) {
float_values.append(value); return value;
}); });
} };
auto reference_box = m_box.paint_box()->absolute_rect();
auto width = CSS::Length::make_px(reference_box.width());
auto height = CSS::Length::make_px(reference_box.height());
switch (transformation.function) { switch (transformation.function) {
case CSS::TransformFunction::Matrix: case CSS::TransformFunction::Matrix:
if (float_values.size() == 6) if (count == 6)
return Gfx::FloatMatrix4x4(float_values[0], float_values[2], 0, float_values[4], return Gfx::FloatMatrix4x4(value(0, width), value(2, width), 0, value(4, width),
float_values[1], float_values[3], 0, float_values[5], value(1, height), value(3, height), 0, value(5, height),
0, 0, 1, 0, 0, 0, 1, 0,
0, 0, 0, 1); 0, 0, 0, 1);
break; break;
case CSS::TransformFunction::Translate: case CSS::TransformFunction::Translate:
if (float_values.size() == 1) if (count == 1)
return Gfx::FloatMatrix4x4(1, 0, 0, float_values[0], return Gfx::FloatMatrix4x4(1, 0, 0, value(0, width),
0, 1, 0, 0, 0, 1, 0, 0,
0, 0, 1, 0, 0, 0, 1, 0,
0, 0, 0, 1); 0, 0, 0, 1);
if (float_values.size() == 2) if (count == 2)
return Gfx::FloatMatrix4x4(1, 0, 0, float_values[0], return Gfx::FloatMatrix4x4(1, 0, 0, value(0, width),
0, 1, 0, float_values[1], 0, 1, 0, value(1, height),
0, 0, 1, 0, 0, 0, 1, 0,
0, 0, 0, 1); 0, 0, 0, 1);
break; break;
case CSS::TransformFunction::TranslateX: case CSS::TransformFunction::TranslateX:
if (float_values.size() == 1) if (count == 1)
return Gfx::FloatMatrix4x4(1, 0, 0, float_values[0], return Gfx::FloatMatrix4x4(1, 0, 0, value(0, width),
0, 1, 0, 0, 0, 1, 0, 0,
0, 0, 1, 0, 0, 0, 1, 0,
0, 0, 0, 1); 0, 0, 0, 1);
break; break;
case CSS::TransformFunction::TranslateY: case CSS::TransformFunction::TranslateY:
if (float_values.size() == 1) if (count == 1)
return Gfx::FloatMatrix4x4(1, 0, 0, 0, return Gfx::FloatMatrix4x4(1, 0, 0, 0,
0, 1, 0, float_values[0], 0, 1, 0, value(0, height),
0, 0, 1, 0, 0, 0, 1, 0,
0, 0, 0, 1); 0, 0, 0, 1);
break; break;
case CSS::TransformFunction::Scale: case CSS::TransformFunction::Scale:
if (float_values.size() == 1) if (count == 1)
return Gfx::FloatMatrix4x4(float_values[0], 0, 0, 0, return Gfx::FloatMatrix4x4(value(0, width), 0, 0, 0,
0, float_values[0], 0, 0, 0, value(0, height), 0, 0,
0, 0, 1, 0, 0, 0, 1, 0,
0, 0, 0, 1); 0, 0, 0, 1);
if (float_values.size() == 2) if (count == 2)
return Gfx::FloatMatrix4x4(float_values[0], 0, 0, 0, return Gfx::FloatMatrix4x4(value(0, width), 0, 0, 0,
0, float_values[1], 0, 0, 0, value(0, height), 0, 0,
0, 0, 1, 0, 0, 0, 1, 0,
0, 0, 0, 1); 0, 0, 0, 1);
break; break;
case CSS::TransformFunction::ScaleX: case CSS::TransformFunction::ScaleX:
if (float_values.size() == 1) if (count == 1)
return Gfx::FloatMatrix4x4(float_values[0], 0, 0, 0, return Gfx::FloatMatrix4x4(value(0, width), 0, 0, 0,
0, 1, 0, 0, 0, 1, 0, 0,
0, 0, 1, 0, 0, 0, 1, 0,
0, 0, 0, 1); 0, 0, 0, 1);
break; break;
case CSS::TransformFunction::ScaleY: case CSS::TransformFunction::ScaleY:
if (float_values.size() == 1) if (count == 1)
return Gfx::FloatMatrix4x4(1, 0, 0, 0, return Gfx::FloatMatrix4x4(1, 0, 0, 0,
0, float_values[0], 0, 0, 0, value(0, height), 0, 0,
0, 0, 1, 0, 0, 0, 1, 0,
0, 0, 0, 1); 0, 0, 0, 1);
break; break;