mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 13:37:45 +00:00
LibWeb: Add PositionValue class to represent CSS <position>
s
This class represents a <position> and handles resolving it to a Gfx::FloatPoint relative to some rectangle. It can handle all forms of <position>: - Two presets: left center - A preset + a length percentage: 10% bottom - Or relative to some edges: right 20% bottom 30px
This commit is contained in:
parent
067759c0e9
commit
e568c93404
2 changed files with 141 additions and 0 deletions
|
@ -1853,6 +1853,108 @@ void LinearGradientStyleValue::paint(PaintContext& context, Gfx::IntRect const&
|
|||
Painting::paint_linear_gradient(context, dest_rect, m_resolved->data);
|
||||
}
|
||||
|
||||
Gfx::FloatPoint PositionValue::resolved(Layout::Node const& node, Gfx::FloatRect const& rect) const
|
||||
{
|
||||
// Note: A preset + a none default x/y_relative_to is impossible in the syntax (and makes little sense)
|
||||
float x = horizontal_position.visit(
|
||||
[&](HorizontalPreset preset) {
|
||||
return rect.width() * [&] {
|
||||
switch (preset) {
|
||||
case HorizontalPreset::Left:
|
||||
return 0.0f;
|
||||
case HorizontalPreset::Center:
|
||||
return 0.5f;
|
||||
case HorizontalPreset::Right:
|
||||
return 1.0f;
|
||||
default:
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
}();
|
||||
},
|
||||
[&](LengthPercentage length_percentage) {
|
||||
return length_percentage.resolved(node, Length::make_px(rect.width())).to_px(node);
|
||||
});
|
||||
float y = vertical_position.visit(
|
||||
[&](VerticalPreset preset) {
|
||||
return rect.height() * [&] {
|
||||
switch (preset) {
|
||||
case VerticalPreset::Top:
|
||||
return 0.0f;
|
||||
case VerticalPreset::Center:
|
||||
return 0.5f;
|
||||
case VerticalPreset::Bottom:
|
||||
return 1.0f;
|
||||
default:
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
}();
|
||||
},
|
||||
[&](LengthPercentage length_percentage) {
|
||||
return length_percentage.resolved(node, Length::make_px(rect.height())).to_px(node);
|
||||
});
|
||||
if (x_relative_to == HorizontalEdge::Right)
|
||||
x = rect.width() - x;
|
||||
if (y_relative_to == VerticalEdge::Bottom)
|
||||
y = rect.height() - y;
|
||||
return Gfx::FloatPoint { rect.x() + x, rect.y() + y };
|
||||
}
|
||||
|
||||
void PositionValue::serialize(StringBuilder& builder) const
|
||||
{
|
||||
// Note: This means our serialization with simplify any with explicit edges that are just `top left`.
|
||||
bool has_relative_edges = x_relative_to == HorizontalEdge::Right || y_relative_to == VerticalEdge::Bottom;
|
||||
if (has_relative_edges)
|
||||
builder.append(x_relative_to == HorizontalEdge::Left ? "left "sv : "right "sv);
|
||||
horizontal_position.visit(
|
||||
[&](HorizontalPreset preset) {
|
||||
builder.append([&] {
|
||||
switch (preset) {
|
||||
case HorizontalPreset::Left:
|
||||
return "left"sv;
|
||||
case HorizontalPreset::Center:
|
||||
return "center"sv;
|
||||
case HorizontalPreset::Right:
|
||||
return "right"sv;
|
||||
default:
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
}());
|
||||
},
|
||||
[&](LengthPercentage length_percentage) {
|
||||
builder.append(length_percentage.to_string());
|
||||
});
|
||||
builder.append(' ');
|
||||
if (has_relative_edges)
|
||||
builder.append(y_relative_to == VerticalEdge::Top ? "top "sv : "bottom "sv);
|
||||
vertical_position.visit(
|
||||
[&](VerticalPreset preset) {
|
||||
builder.append([&] {
|
||||
switch (preset) {
|
||||
case VerticalPreset::Top:
|
||||
return "top"sv;
|
||||
case VerticalPreset::Center:
|
||||
return "center"sv;
|
||||
case VerticalPreset::Bottom:
|
||||
return "bottom"sv;
|
||||
default:
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
}());
|
||||
},
|
||||
[&](LengthPercentage length_percentage) {
|
||||
builder.append(length_percentage.to_string());
|
||||
});
|
||||
}
|
||||
|
||||
bool PositionValue::operator==(PositionValue const& other) const
|
||||
{
|
||||
return (
|
||||
x_relative_to == other.x_relative_to
|
||||
&& y_relative_to == other.y_relative_to
|
||||
&& variant_equals(horizontal_position, other.horizontal_position)
|
||||
&& variant_equals(vertical_position, other.vertical_position));
|
||||
}
|
||||
|
||||
String ConicGradientStyleValue::to_string() const
|
||||
{
|
||||
StringBuilder builder;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue