1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-06-28 18:22:12 +00:00

LibWeb: Change paint_all_borders() to accept only device pixel values

By consistently accepting only device pixel values instead of a mix of
CSSPixels and DevicePixels values, we can simplify the implementation
of paint_border() and paint_all_borders().
This commit is contained in:
Aliaksandr Kalenik 2023-11-19 22:03:48 +01:00 committed by Andreas Kling
parent ae8c98104a
commit 70353b79af
9 changed files with 152 additions and 88 deletions

View file

@ -482,6 +482,7 @@ set(SOURCES
Painting/BorderRadiiData.cpp Painting/BorderRadiiData.cpp
Painting/BorderPainting.cpp Painting/BorderPainting.cpp
Painting/BorderRadiusCornerClipper.cpp Painting/BorderRadiusCornerClipper.cpp
Painting/BordersData.cpp
Painting/ButtonPaintable.cpp Painting/ButtonPaintable.cpp
Painting/CanvasPaintable.cpp Painting/CanvasPaintable.cpp
Painting/CheckBoxPaintable.cpp Painting/CheckBoxPaintable.cpp

View file

@ -85,7 +85,7 @@ static Color dark_color_for_inset_and_outset(Color const& color)
return Color::from_hsv({ hsv.hue, hsv.saturation, hsv.value - dark_light_absolute_value_difference }); return Color::from_hsv({ hsv.hue, hsv.saturation, hsv.value - dark_light_absolute_value_difference });
} }
Gfx::Color border_color(BorderEdge edge, BordersData const& borders_data) Gfx::Color border_color(BorderEdge edge, BordersDataDevicePixels const& borders_data)
{ {
auto const& border_data = [&] { auto const& border_data = [&] {
switch (edge) { switch (edge) {
@ -115,7 +115,7 @@ Gfx::Color border_color(BorderEdge edge, BordersData const& borders_data)
return border_data.color; return border_data.color;
} }
void paint_border(PaintContext& context, BorderEdge edge, DevicePixelRect const& rect, Gfx::AntiAliasingPainter::CornerRadius const& radius, Gfx::AntiAliasingPainter::CornerRadius const& opposite_radius, BordersData const& borders_data, Gfx::Path& path, bool last) void paint_border(RecordingPainter& painter, BorderEdge edge, DevicePixelRect const& rect, Gfx::AntiAliasingPainter::CornerRadius const& radius, Gfx::AntiAliasingPainter::CornerRadius const& opposite_radius, BordersDataDevicePixels const& borders_data, Gfx::Path& path, bool last)
{ {
auto const& border_data = [&] { auto const& border_data = [&] {
switch (edge) { switch (edge) {
@ -130,13 +130,11 @@ void paint_border(PaintContext& context, BorderEdge edge, DevicePixelRect const&
} }
}(); }();
CSSPixels width = border_data.width; if (border_data.width <= 0)
if (width <= 0)
return; return;
auto color = border_color(edge, borders_data); auto color = border_color(edge, borders_data);
auto border_style = border_data.line_style; auto border_style = border_data.line_style;
auto device_pixel_width = context.rounded_device_pixels(width);
struct Points { struct Points {
DevicePixelPoint p1; DevicePixelPoint p1;
@ -183,27 +181,27 @@ void paint_border(PaintContext& context, BorderEdge edge, DevicePixelRect const&
auto [p1, p2] = points_for_edge(edge, rect); auto [p1, p2] = points_for_edge(edge, rect);
switch (edge) { switch (edge) {
case BorderEdge::Top: case BorderEdge::Top:
p1.translate_by(device_pixel_width / 2, device_pixel_width / 2); p1.translate_by(border_data.width / 2, border_data.width / 2);
p2.translate_by(-device_pixel_width / 2, device_pixel_width / 2); p2.translate_by(-border_data.width / 2, border_data.width / 2);
break; break;
case BorderEdge::Right: case BorderEdge::Right:
p1.translate_by(-device_pixel_width / 2, device_pixel_width / 2); p1.translate_by(-border_data.width / 2, border_data.width / 2);
p2.translate_by(-device_pixel_width / 2, -device_pixel_width / 2); p2.translate_by(-border_data.width / 2, -border_data.width / 2);
break; break;
case BorderEdge::Bottom: case BorderEdge::Bottom:
p1.translate_by(device_pixel_width / 2, -device_pixel_width / 2); p1.translate_by(border_data.width / 2, -border_data.width / 2);
p2.translate_by(-device_pixel_width / 2, -device_pixel_width / 2); p2.translate_by(-border_data.width / 2, -border_data.width / 2);
break; break;
case BorderEdge::Left: case BorderEdge::Left:
p1.translate_by(device_pixel_width / 2, device_pixel_width / 2); p1.translate_by(border_data.width / 2, border_data.width / 2);
p2.translate_by(device_pixel_width / 2, -device_pixel_width / 2); p2.translate_by(border_data.width / 2, -border_data.width / 2);
break; break;
} }
if (border_style == CSS::LineStyle::Dotted) { if (border_style == CSS::LineStyle::Dotted) {
context.painter().draw_line(p1.to_type<int>(), p2.to_type<int>(), color, device_pixel_width.value(), gfx_line_style); painter.draw_line(p1.to_type<int>(), p2.to_type<int>(), color, border_data.width.value(), gfx_line_style);
return; return;
} }
context.painter().draw_line(p1.to_type<int>(), p2.to_type<int>(), color, device_pixel_width.value(), gfx_line_style); painter.draw_line(p1.to_type<int>(), p2.to_type<int>(), color, border_data.width.value(), gfx_line_style);
return; return;
} }
@ -245,7 +243,7 @@ void paint_border(PaintContext& context, BorderEdge edge, DevicePixelRect const&
// If joined borders have the same color, combine them to draw together. // If joined borders have the same color, combine them to draw together.
if (ready_to_draw) { if (ready_to_draw) {
path.close_all_subpaths(); path.close_all_subpaths();
context.painter().fill_path({ .path = path, .color = color, .winding_rule = Gfx::Painter::WindingRule::EvenOdd }); painter.fill_path({ .path = path, .color = color, .winding_rule = Gfx::Painter::WindingRule::EvenOdd });
path.clear(); path.clear();
} }
}; };
@ -285,10 +283,10 @@ void paint_border(PaintContext& context, BorderEdge edge, DevicePixelRect const&
*/ */
switch (edge) { switch (edge) {
case BorderEdge::Top: { case BorderEdge::Top: {
auto joined_border_width = context.enclosing_device_pixels(borders_data.left.width); auto joined_border_width = borders_data.left.width;
auto opposite_joined_border_width = context.enclosing_device_pixels(borders_data.right.width); auto opposite_joined_border_width = borders_data.right.width;
bool joined_corner_has_inner_corner = device_pixel_width < radius.vertical_radius && joined_border_width < radius.horizontal_radius; bool joined_corner_has_inner_corner = border_data.width < radius.vertical_radius && joined_border_width < radius.horizontal_radius;
bool opposite_joined_corner_has_inner_corner = device_pixel_width < opposite_radius.vertical_radius && opposite_joined_border_width < opposite_radius.horizontal_radius; bool opposite_joined_corner_has_inner_corner = border_data.width < opposite_radius.vertical_radius && opposite_joined_border_width < opposite_radius.horizontal_radius;
Gfx::FloatPoint joined_corner_endpoint_offset; Gfx::FloatPoint joined_corner_endpoint_offset;
Gfx::FloatPoint opposite_joined_border_corner_offset; Gfx::FloatPoint opposite_joined_border_corner_offset;
@ -310,11 +308,11 @@ void paint_border(PaintContext& context, BorderEdge edge, DevicePixelRect const&
if (joined_corner_has_inner_corner) { if (joined_corner_has_inner_corner) {
Gfx::FloatPoint midpoint = compute_midpoint( Gfx::FloatPoint midpoint = compute_midpoint(
radius.horizontal_radius - joined_border_width.value(), radius.horizontal_radius - joined_border_width.value(),
radius.vertical_radius - device_pixel_width.value(), radius.vertical_radius - border_data.width.value(),
joined_border_width.value()); joined_border_width.value());
Gfx::FloatPoint inner_corner_endpoint_offset = Gfx::FloatPoint( Gfx::FloatPoint inner_corner_endpoint_offset = Gfx::FloatPoint(
-midpoint.x(), -midpoint.x(),
radius.vertical_radius - device_pixel_width.value() - midpoint.y()); radius.vertical_radius - border_data.width.value() - midpoint.y());
points.append(Gfx::FloatPoint(rect.bottom_left().to_type<int>()) + inner_corner_endpoint_offset); points.append(Gfx::FloatPoint(rect.bottom_left().to_type<int>()) + inner_corner_endpoint_offset);
points.append(Gfx::FloatPoint(rect.bottom_left().to_type<int>())); points.append(Gfx::FloatPoint(rect.bottom_left().to_type<int>()));
} else { } else {
@ -327,11 +325,11 @@ void paint_border(PaintContext& context, BorderEdge edge, DevicePixelRect const&
if (opposite_joined_corner_has_inner_corner) { if (opposite_joined_corner_has_inner_corner) {
Gfx::FloatPoint midpoint = compute_midpoint( Gfx::FloatPoint midpoint = compute_midpoint(
opposite_radius.horizontal_radius - opposite_joined_border_width.value(), opposite_radius.horizontal_radius - opposite_joined_border_width.value(),
opposite_radius.vertical_radius - device_pixel_width.value(), opposite_radius.vertical_radius - border_data.width.value(),
opposite_joined_border_width.value()); opposite_joined_border_width.value());
Gfx::FloatPoint inner_corner_endpoint_offset = Gfx::FloatPoint( Gfx::FloatPoint inner_corner_endpoint_offset = Gfx::FloatPoint(
midpoint.x(), midpoint.x(),
opposite_radius.vertical_radius - device_pixel_width.value() - midpoint.y()); opposite_radius.vertical_radius - border_data.width.value() - midpoint.y());
points.append(Gfx::FloatPoint(rect.bottom_right().to_type<int>())); points.append(Gfx::FloatPoint(rect.bottom_right().to_type<int>()));
points.append(Gfx::FloatPoint(rect.bottom_right().to_type<int>()) + inner_corner_endpoint_offset); points.append(Gfx::FloatPoint(rect.bottom_right().to_type<int>()) + inner_corner_endpoint_offset);
} else { } else {
@ -348,16 +346,16 @@ void paint_border(PaintContext& context, BorderEdge edge, DevicePixelRect const&
points, points,
joined_corner_has_inner_corner, joined_corner_has_inner_corner,
opposite_joined_corner_has_inner_corner, opposite_joined_corner_has_inner_corner,
Gfx::FloatSize(joined_border_width.value(), device_pixel_width.value()), Gfx::FloatSize(joined_border_width.value(), border_data.width.value()),
Gfx::FloatSize(opposite_joined_border_width.value(), device_pixel_width.value()), Gfx::FloatSize(opposite_joined_border_width.value(), border_data.width.value()),
last || color != border_color(BorderEdge::Right, borders_data)); last || color != border_color(BorderEdge::Right, borders_data));
break; break;
} }
case BorderEdge::Right: { case BorderEdge::Right: {
auto joined_border_width = context.enclosing_device_pixels(borders_data.top.width); auto joined_border_width = borders_data.top.width;
auto opposite_joined_border_width = context.enclosing_device_pixels(borders_data.bottom.width); auto opposite_joined_border_width = borders_data.bottom.width;
bool joined_corner_has_inner_corner = device_pixel_width < radius.horizontal_radius && joined_border_width < radius.vertical_radius; bool joined_corner_has_inner_corner = border_data.width < radius.horizontal_radius && joined_border_width < radius.vertical_radius;
bool opposite_joined_corner_has_inner_corner = device_pixel_width < opposite_radius.horizontal_radius && opposite_joined_border_width < opposite_radius.vertical_radius; bool opposite_joined_corner_has_inner_corner = border_data.width < opposite_radius.horizontal_radius && opposite_joined_border_width < opposite_radius.vertical_radius;
Gfx::FloatPoint joined_corner_endpoint_offset; Gfx::FloatPoint joined_corner_endpoint_offset;
Gfx::FloatPoint opposite_joined_border_corner_offset; Gfx::FloatPoint opposite_joined_border_corner_offset;
@ -378,11 +376,11 @@ void paint_border(PaintContext& context, BorderEdge edge, DevicePixelRect const&
if (joined_corner_has_inner_corner) { if (joined_corner_has_inner_corner) {
auto midpoint = compute_midpoint( auto midpoint = compute_midpoint(
radius.horizontal_radius - device_pixel_width.value(), radius.horizontal_radius - border_data.width.value(),
radius.vertical_radius - joined_border_width.value(), radius.vertical_radius - joined_border_width.value(),
joined_border_width.value()); joined_border_width.value());
Gfx::FloatPoint inner_corner = Gfx::FloatPoint( Gfx::FloatPoint inner_corner = Gfx::FloatPoint(
-(radius.horizontal_radius - midpoint.x() - device_pixel_width.value()), -(radius.horizontal_radius - midpoint.x() - border_data.width.value()),
-midpoint.y()); -midpoint.y());
points.append(Gfx::FloatPoint(rect.top_left().to_type<int>()) + inner_corner); points.append(Gfx::FloatPoint(rect.top_left().to_type<int>()) + inner_corner);
points.append(Gfx::FloatPoint(rect.top_left().to_type<int>())); points.append(Gfx::FloatPoint(rect.top_left().to_type<int>()));
@ -393,11 +391,11 @@ void paint_border(PaintContext& context, BorderEdge edge, DevicePixelRect const&
if (opposite_joined_corner_has_inner_corner) { if (opposite_joined_corner_has_inner_corner) {
auto midpoint = compute_midpoint( auto midpoint = compute_midpoint(
opposite_radius.horizontal_radius - device_pixel_width.value(), opposite_radius.horizontal_radius - border_data.width.value(),
opposite_radius.vertical_radius - opposite_joined_border_width.value(), opposite_radius.vertical_radius - opposite_joined_border_width.value(),
opposite_joined_border_width.value()); opposite_joined_border_width.value());
Gfx::FloatPoint inner_corner = Gfx::FloatPoint( Gfx::FloatPoint inner_corner = Gfx::FloatPoint(
-(opposite_radius.horizontal_radius - midpoint.x() - device_pixel_width.value()), -(opposite_radius.horizontal_radius - midpoint.x() - border_data.width.value()),
midpoint.y()); midpoint.y());
points.append(Gfx::FloatPoint(rect.bottom_left().to_type<int>())); points.append(Gfx::FloatPoint(rect.bottom_left().to_type<int>()));
points.append(Gfx::FloatPoint(rect.bottom_left().to_type<int>()) + inner_corner); points.append(Gfx::FloatPoint(rect.bottom_left().to_type<int>()) + inner_corner);
@ -413,16 +411,16 @@ void paint_border(PaintContext& context, BorderEdge edge, DevicePixelRect const&
points, points,
joined_corner_has_inner_corner, joined_corner_has_inner_corner,
opposite_joined_corner_has_inner_corner, opposite_joined_corner_has_inner_corner,
Gfx::FloatSize(device_pixel_width.value(), joined_border_width.value()), Gfx::FloatSize(border_data.width.value(), joined_border_width.value()),
Gfx::FloatSize(device_pixel_width.value(), opposite_joined_border_width.value()), Gfx::FloatSize(border_data.width.value(), opposite_joined_border_width.value()),
last || color != border_color(BorderEdge::Bottom, borders_data)); last || color != border_color(BorderEdge::Bottom, borders_data));
break; break;
} }
case BorderEdge::Bottom: { case BorderEdge::Bottom: {
auto joined_border_width = context.enclosing_device_pixels(borders_data.right.width); auto joined_border_width = borders_data.right.width;
auto opposite_joined_border_width = context.enclosing_device_pixels(borders_data.left.width); auto opposite_joined_border_width = borders_data.left.width;
bool joined_corner_has_inner_corner = device_pixel_width < radius.vertical_radius && joined_border_width < radius.horizontal_radius; bool joined_corner_has_inner_corner = border_data.width < radius.vertical_radius && joined_border_width < radius.horizontal_radius;
bool opposite_joined_corner_has_inner_corner = device_pixel_width < opposite_radius.vertical_radius && opposite_joined_border_width < opposite_radius.horizontal_radius; bool opposite_joined_corner_has_inner_corner = border_data.width < opposite_radius.vertical_radius && opposite_joined_border_width < opposite_radius.horizontal_radius;
Gfx::FloatPoint joined_corner_endpoint_offset; Gfx::FloatPoint joined_corner_endpoint_offset;
Gfx::FloatPoint opposite_joined_border_corner_offset; Gfx::FloatPoint opposite_joined_border_corner_offset;
@ -444,9 +442,9 @@ void paint_border(PaintContext& context, BorderEdge edge, DevicePixelRect const&
if (joined_corner_has_inner_corner) { if (joined_corner_has_inner_corner) {
auto midpoint = compute_midpoint( auto midpoint = compute_midpoint(
radius.horizontal_radius - joined_border_width.value(), radius.horizontal_radius - joined_border_width.value(),
radius.vertical_radius - device_pixel_width.value(), radius.vertical_radius - border_data.width.value(),
joined_border_width.value()); joined_border_width.value());
Gfx::FloatPoint inner_corner = Gfx::FloatPoint(midpoint.x(), -(radius.vertical_radius - midpoint.y() - device_pixel_width.value())); Gfx::FloatPoint inner_corner = Gfx::FloatPoint(midpoint.x(), -(radius.vertical_radius - midpoint.y() - border_data.width.value()));
points.append(Gfx::FloatPoint(rect.top_right().to_type<int>()) + inner_corner); points.append(Gfx::FloatPoint(rect.top_right().to_type<int>()) + inner_corner);
points.append(Gfx::FloatPoint(rect.top_right().to_type<int>())); points.append(Gfx::FloatPoint(rect.top_right().to_type<int>()));
} else { } else {
@ -457,11 +455,11 @@ void paint_border(PaintContext& context, BorderEdge edge, DevicePixelRect const&
if (opposite_joined_corner_has_inner_corner) { if (opposite_joined_corner_has_inner_corner) {
auto midpoint = compute_midpoint( auto midpoint = compute_midpoint(
opposite_radius.horizontal_radius - opposite_joined_border_width.value(), opposite_radius.horizontal_radius - opposite_joined_border_width.value(),
opposite_radius.vertical_radius - device_pixel_width.value(), opposite_radius.vertical_radius - border_data.width.value(),
opposite_joined_border_width.value()); opposite_joined_border_width.value());
Gfx::FloatPoint inner_corner = Gfx::FloatPoint( Gfx::FloatPoint inner_corner = Gfx::FloatPoint(
-midpoint.x(), -midpoint.x(),
-(opposite_radius.vertical_radius - midpoint.y() - device_pixel_width.value())); -(opposite_radius.vertical_radius - midpoint.y() - border_data.width.value()));
points.append(Gfx::FloatPoint(rect.top_left().to_type<int>())); points.append(Gfx::FloatPoint(rect.top_left().to_type<int>()));
points.append(Gfx::FloatPoint(rect.top_left().to_type<int>()) + inner_corner); points.append(Gfx::FloatPoint(rect.top_left().to_type<int>()) + inner_corner);
} else { } else {
@ -475,16 +473,16 @@ void paint_border(PaintContext& context, BorderEdge edge, DevicePixelRect const&
points, points,
joined_corner_has_inner_corner, joined_corner_has_inner_corner,
opposite_joined_corner_has_inner_corner, opposite_joined_corner_has_inner_corner,
Gfx::FloatSize(joined_border_width.value(), device_pixel_width.value()), Gfx::FloatSize(joined_border_width.value(), border_data.width.value()),
Gfx::FloatSize(opposite_joined_border_width.value(), device_pixel_width.value()), Gfx::FloatSize(opposite_joined_border_width.value(), border_data.width.value()),
last || color != border_color(BorderEdge::Left, borders_data)); last || color != border_color(BorderEdge::Left, borders_data));
break; break;
} }
case BorderEdge::Left: { case BorderEdge::Left: {
auto joined_border_width = context.enclosing_device_pixels(borders_data.bottom.width); auto joined_border_width = borders_data.bottom.width;
auto opposite_joined_border_width = context.enclosing_device_pixels(borders_data.top.width); auto opposite_joined_border_width = borders_data.top.width;
bool joined_corner_has_inner_corner = device_pixel_width < radius.horizontal_radius && joined_border_width < radius.vertical_radius; bool joined_corner_has_inner_corner = border_data.width < radius.horizontal_radius && joined_border_width < radius.vertical_radius;
bool opposite_joined_corner_has_inner_corner = device_pixel_width < opposite_radius.horizontal_radius && opposite_joined_border_width < opposite_radius.vertical_radius; bool opposite_joined_corner_has_inner_corner = border_data.width < opposite_radius.horizontal_radius && opposite_joined_border_width < opposite_radius.vertical_radius;
Gfx::FloatPoint joined_corner_endpoint_offset; Gfx::FloatPoint joined_corner_endpoint_offset;
Gfx::FloatPoint opposite_joined_border_corner_offset; Gfx::FloatPoint opposite_joined_border_corner_offset;
@ -505,10 +503,10 @@ void paint_border(PaintContext& context, BorderEdge edge, DevicePixelRect const&
if (joined_corner_has_inner_corner) { if (joined_corner_has_inner_corner) {
auto midpoint = compute_midpoint( auto midpoint = compute_midpoint(
radius.horizontal_radius - device_pixel_width.value(), radius.horizontal_radius - border_data.width.value(),
radius.vertical_radius - joined_border_width.value(), radius.vertical_radius - joined_border_width.value(),
joined_border_width.value()); joined_border_width.value());
Gfx::FloatPoint inner_corner = Gfx::FloatPoint(radius.horizontal_radius - device_pixel_width.value() - midpoint.x(), midpoint.y()); Gfx::FloatPoint inner_corner = Gfx::FloatPoint(radius.horizontal_radius - border_data.width.value() - midpoint.x(), midpoint.y());
points.append(Gfx::FloatPoint(rect.bottom_right().to_type<int>()) + inner_corner); points.append(Gfx::FloatPoint(rect.bottom_right().to_type<int>()) + inner_corner);
points.append(Gfx::FloatPoint(rect.bottom_right().to_type<int>())); points.append(Gfx::FloatPoint(rect.bottom_right().to_type<int>()));
} else { } else {
@ -518,11 +516,11 @@ void paint_border(PaintContext& context, BorderEdge edge, DevicePixelRect const&
if (opposite_joined_corner_has_inner_corner) { if (opposite_joined_corner_has_inner_corner) {
auto midpoint = compute_midpoint( auto midpoint = compute_midpoint(
opposite_radius.horizontal_radius - device_pixel_width.value(), opposite_radius.horizontal_radius - border_data.width.value(),
opposite_radius.vertical_radius - opposite_joined_border_width.value(), opposite_radius.vertical_radius - opposite_joined_border_width.value(),
opposite_joined_border_width.value()); opposite_joined_border_width.value());
Gfx::FloatPoint inner_corner = Gfx::FloatPoint( Gfx::FloatPoint inner_corner = Gfx::FloatPoint(
opposite_radius.horizontal_radius - device_pixel_width.value() - midpoint.x(), opposite_radius.horizontal_radius - border_data.width.value() - midpoint.x(),
-midpoint.y()); -midpoint.y());
points.append(Gfx::FloatPoint(rect.top_right().to_type<int>())); points.append(Gfx::FloatPoint(rect.top_right().to_type<int>()));
points.append(Gfx::FloatPoint(rect.top_right().to_type<int>()) + inner_corner); points.append(Gfx::FloatPoint(rect.top_right().to_type<int>()) + inner_corner);
@ -537,23 +535,23 @@ void paint_border(PaintContext& context, BorderEdge edge, DevicePixelRect const&
points, points,
joined_corner_has_inner_corner, joined_corner_has_inner_corner,
opposite_joined_corner_has_inner_corner, opposite_joined_corner_has_inner_corner,
Gfx::FloatSize(device_pixel_width.value(), joined_border_width.value()), Gfx::FloatSize(border_data.width.value(), joined_border_width.value()),
Gfx::FloatSize(device_pixel_width.value(), opposite_joined_border_width.value()), Gfx::FloatSize(border_data.width.value(), opposite_joined_border_width.value()),
last || color != border_color(BorderEdge::Top, borders_data)); last || color != border_color(BorderEdge::Top, borders_data));
break; break;
} }
} }
} }
void paint_all_borders(PaintContext& context, DevicePixelRect const& border_rect, BorderRadiiData const& border_radii_data, BordersData const& borders_data) void paint_all_borders(RecordingPainter& painter, DevicePixelRect const& border_rect, CornerRadii const& corner_radii, BordersDataDevicePixels const& borders_data)
{ {
if (borders_data.top.width <= 0 && borders_data.right.width <= 0 && borders_data.left.width <= 0 && borders_data.bottom.width <= 0) if (borders_data.top.width <= 0 && borders_data.right.width <= 0 && borders_data.left.width <= 0 && borders_data.bottom.width <= 0)
return; return;
auto top_left = border_radii_data.top_left.as_corner(context); auto top_left = corner_radii.top_left;
auto top_right = border_radii_data.top_right.as_corner(context); auto top_right = corner_radii.top_right;
auto bottom_right = border_radii_data.bottom_right.as_corner(context); auto bottom_right = corner_radii.bottom_right;
auto bottom_left = border_radii_data.bottom_left.as_corner(context); auto bottom_left = corner_radii.bottom_left;
// Disable border radii if the corresponding borders don't exist: // Disable border radii if the corresponding borders don't exist:
if (borders_data.bottom.width <= 0 && borders_data.left.width <= 0) if (borders_data.bottom.width <= 0 && borders_data.left.width <= 0)
@ -569,24 +567,24 @@ void paint_all_borders(PaintContext& context, DevicePixelRect const& border_rect
border_rect.x() + top_left.horizontal_radius, border_rect.x() + top_left.horizontal_radius,
border_rect.y(), border_rect.y(),
border_rect.width() - top_left.horizontal_radius - top_right.horizontal_radius, border_rect.width() - top_left.horizontal_radius - top_right.horizontal_radius,
context.enclosing_device_pixels(borders_data.top.width) borders_data.top.width
}; };
DevicePixelRect right_border_rect = { DevicePixelRect right_border_rect = {
border_rect.x() + (border_rect.width() - context.enclosing_device_pixels(borders_data.right.width)), border_rect.x() + (border_rect.width() - borders_data.right.width),
border_rect.y() + top_right.vertical_radius, border_rect.y() + top_right.vertical_radius,
context.enclosing_device_pixels(borders_data.right.width), borders_data.right.width,
border_rect.height() - top_right.vertical_radius - bottom_right.vertical_radius border_rect.height() - top_right.vertical_radius - bottom_right.vertical_radius
}; };
DevicePixelRect bottom_border_rect = { DevicePixelRect bottom_border_rect = {
border_rect.x() + bottom_left.horizontal_radius, border_rect.x() + bottom_left.horizontal_radius,
border_rect.y() + (border_rect.height() - context.enclosing_device_pixels(borders_data.bottom.width)), border_rect.y() + (border_rect.height() - borders_data.bottom.width),
border_rect.width() - bottom_left.horizontal_radius - bottom_right.horizontal_radius, border_rect.width() - bottom_left.horizontal_radius - bottom_right.horizontal_radius,
context.enclosing_device_pixels(borders_data.bottom.width) borders_data.bottom.width
}; };
DevicePixelRect left_border_rect = { DevicePixelRect left_border_rect = {
border_rect.x(), border_rect.x(),
border_rect.y() + top_left.vertical_radius, border_rect.y() + top_left.vertical_radius,
context.enclosing_device_pixels(borders_data.left.width), borders_data.left.width,
border_rect.height() - top_left.vertical_radius - bottom_left.vertical_radius border_rect.height() - top_left.vertical_radius - bottom_left.vertical_radius
}; };
@ -611,16 +609,16 @@ void paint_all_borders(PaintContext& context, DevicePixelRect const& border_rect
for (BorderEdge edge : borders) { for (BorderEdge edge : borders) {
switch (edge) { switch (edge) {
case BorderEdge::Top: case BorderEdge::Top:
paint_border(context, BorderEdge::Top, top_border_rect, top_left, top_right, borders_data, path, edge == borders.last()); paint_border(painter, BorderEdge::Top, top_border_rect, top_left, top_right, borders_data, path, edge == borders.last());
break; break;
case BorderEdge::Right: case BorderEdge::Right:
paint_border(context, BorderEdge::Right, right_border_rect, top_right, bottom_right, borders_data, path, edge == borders.last()); paint_border(painter, BorderEdge::Right, right_border_rect, top_right, bottom_right, borders_data, path, edge == borders.last());
break; break;
case BorderEdge::Bottom: case BorderEdge::Bottom:
paint_border(context, BorderEdge::Bottom, bottom_border_rect, bottom_right, bottom_left, borders_data, path, edge == borders.last()); paint_border(painter, BorderEdge::Bottom, bottom_border_rect, bottom_right, bottom_left, borders_data, path, edge == borders.last());
break; break;
case BorderEdge::Left: case BorderEdge::Left:
paint_border(context, BorderEdge::Left, left_border_rect, bottom_left, top_left, borders_data, path, edge == borders.last()); paint_border(painter, BorderEdge::Left, left_border_rect, bottom_left, top_left, borders_data, path, edge == borders.last());
break; break;
default: default:
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();

View file

@ -28,9 +28,9 @@ enum class BorderEdge {
// Returns OptionalNone if there is no outline to paint. // Returns OptionalNone if there is no outline to paint.
Optional<BordersData> borders_data_for_outline(Layout::Node const&, Color outline_color, CSS::OutlineStyle outline_style, CSSPixels outline_width); Optional<BordersData> borders_data_for_outline(Layout::Node const&, Color outline_color, CSS::OutlineStyle outline_style, CSSPixels outline_width);
void paint_border(PaintContext& context, BorderEdge edge, DevicePixelRect const& rect, Gfx::AntiAliasingPainter::CornerRadius const& radius, Gfx::AntiAliasingPainter::CornerRadius const& opposite_radius, BordersData const& borders_data, Gfx::Path& path, bool last); void paint_border(RecordingPainter& painter, BorderEdge edge, DevicePixelRect const& rect, Gfx::AntiAliasingPainter::CornerRadius const& radius, Gfx::AntiAliasingPainter::CornerRadius const& opposite_radius, BordersDataDevicePixels const& borders_data, Gfx::Path& path, bool last);
void paint_all_borders(PaintContext& context, DevicePixelRect const& border_rect, BorderRadiiData const& border_radii_data, BordersData const&); void paint_all_borders(RecordingPainter& context, DevicePixelRect const& border_rect, CornerRadii const& corner_radii, BordersDataDevicePixels const&);
Gfx::Color border_color(BorderEdge edge, BordersData const& borders_data); Gfx::Color border_color(BorderEdge edge, BordersDataDevicePixels const& borders_data);
} }

View file

@ -33,6 +33,15 @@ struct BorderRadiusData {
} }
}; };
using CornerRadius = Gfx::AntiAliasingPainter::CornerRadius;
struct CornerRadii {
CornerRadius top_left;
CornerRadius top_right;
CornerRadius bottom_right;
CornerRadius bottom_left;
};
struct BorderRadiiData { struct BorderRadiiData {
BorderRadiusData top_left; BorderRadiusData top_left;
BorderRadiusData top_right; BorderRadiusData top_right;
@ -56,15 +65,16 @@ struct BorderRadiiData {
{ {
shrink(-top, -right, -bottom, -left); shrink(-top, -right, -bottom, -left);
} }
};
using CornerRadius = Gfx::AntiAliasingPainter::CornerRadius; inline CornerRadii as_corners(PaintContext& context) const
{
struct CornerRadii { return CornerRadii {
CornerRadius top_left; top_left.as_corner(context),
CornerRadius top_right; top_right.as_corner(context),
CornerRadius bottom_right; bottom_right.as_corner(context),
CornerRadius bottom_left; bottom_left.as_corner(context)
};
}
}; };
} }

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2023, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Painting/BordersData.h>
#include <LibWeb/Painting/PaintContext.h>
namespace Web::Painting {
BordersDataDevicePixels BordersData::to_device_pixels(PaintContext const& context) const
{
return BordersDataDevicePixels {
BorderDataDevicePixels {
top.color,
top.line_style,
context.enclosing_device_pixels(top.width).value() },
BorderDataDevicePixels {
right.color,
right.line_style,
context.enclosing_device_pixels(right.width).value() },
BorderDataDevicePixels {
bottom.color,
bottom.line_style,
context.enclosing_device_pixels(bottom.width).value() },
BorderDataDevicePixels {
left.color,
left.line_style,
context.enclosing_device_pixels(left.width).value() }
};
}
}

View file

@ -7,13 +7,34 @@
#pragma once #pragma once
#include <LibGfx/Color.h>
#include <LibWeb/CSS/ComputedValues.h>
#include <LibWeb/CSS/Enums.h>
#include <LibWeb/PixelUnits.h>
namespace Web::Painting { namespace Web::Painting {
struct BorderDataDevicePixels {
public:
Color color { Color::Transparent };
CSS::LineStyle line_style { CSS::LineStyle::None };
DevicePixels width { 0 };
};
struct BordersDataDevicePixels {
BorderDataDevicePixels top;
BorderDataDevicePixels right;
BorderDataDevicePixels bottom;
BorderDataDevicePixels left;
};
struct BordersData { struct BordersData {
CSS::BorderData top; CSS::BorderData top;
CSS::BorderData right; CSS::BorderData right;
CSS::BorderData bottom; CSS::BorderData bottom;
CSS::BorderData left; CSS::BorderData left;
BordersDataDevicePixels to_device_pixels(PaintContext const& context) const;
}; };
} }

View file

@ -134,9 +134,9 @@ void InlinePaintable::paint(PaintContext& context, PaintPhase phase) const
border_radii_data.inflate(outline_data->top.width + outline_offset_y, outline_data->right.width + outline_offset_x, outline_data->bottom.width + outline_offset_y, outline_data->left.width + outline_offset_x); border_radii_data.inflate(outline_data->top.width + outline_offset_y, outline_data->right.width + outline_offset_x, outline_data->bottom.width + outline_offset_y, outline_data->left.width + outline_offset_x);
borders_rect.inflate(outline_data->top.width + outline_offset_y, outline_data->right.width + outline_offset_x, outline_data->bottom.width + outline_offset_y, outline_data->left.width + outline_offset_x); borders_rect.inflate(outline_data->top.width + outline_offset_y, outline_data->right.width + outline_offset_x, outline_data->bottom.width + outline_offset_y, outline_data->left.width + outline_offset_x);
paint_all_borders(context, context.rounded_device_rect(borders_rect), border_radii_data, *outline_data); paint_all_borders(context.painter(), context.rounded_device_rect(borders_rect), border_radii_data.as_corners(context), outline_data->to_device_pixels(context));
} else { } else {
paint_all_borders(context, context.rounded_device_rect(borders_rect), border_radii_data, borders_data); paint_all_borders(context.painter(), context.rounded_device_rect(borders_rect), border_radii_data.as_corners(context), borders_data.to_device_pixels(context));
} }
return IterationDecision::Continue; return IterationDecision::Continue;

View file

@ -246,7 +246,7 @@ void PaintableBox::paint(PaintContext& context, PaintPhase phase) const
border_radius_data.inflate(outline_width + outline_offset_y, outline_width + outline_offset_x, outline_width + outline_offset_y, outline_width + outline_offset_x); border_radius_data.inflate(outline_width + outline_offset_y, outline_width + outline_offset_x, outline_width + outline_offset_y, outline_width + outline_offset_x);
borders_rect.inflate(outline_width + outline_offset_y, outline_width + outline_offset_x, outline_width + outline_offset_y, outline_width + outline_offset_x); borders_rect.inflate(outline_width + outline_offset_y, outline_width + outline_offset_x, outline_width + outline_offset_y, outline_width + outline_offset_x);
paint_all_borders(context, context.rounded_device_rect(borders_rect), border_radius_data, borders_data.value()); paint_all_borders(context.painter(), context.rounded_device_rect(borders_rect), border_radius_data.as_corners(context), borders_data->to_device_pixels(context));
} }
} }
@ -313,7 +313,7 @@ void PaintableBox::paint_border(PaintContext& context) const
.bottom = box_model().border.bottom == 0 ? CSS::BorderData() : computed_values().border_bottom(), .bottom = box_model().border.bottom == 0 ? CSS::BorderData() : computed_values().border_bottom(),
.left = box_model().border.left == 0 ? CSS::BorderData() : computed_values().border_left(), .left = box_model().border.left == 0 ? CSS::BorderData() : computed_values().border_left(),
}; };
paint_all_borders(context, context.rounded_device_rect(absolute_border_box_rect()), normalized_border_radii_data(), borders_data); paint_all_borders(context.painter(), context.rounded_device_rect(absolute_border_box_rect()), normalized_border_radii_data().as_corners(context), borders_data.to_device_pixels(context));
} }
void PaintableBox::paint_backdrop_filter(PaintContext& context) const void PaintableBox::paint_backdrop_filter(PaintContext& context) const

View file

@ -351,7 +351,7 @@ static void paint_separate_cell_borders(PaintableBox const& cell_box, HashMap<Ce
.left = cell_box.box_model().border.left == 0 ? CSS::BorderData() : cell_box.computed_values().border_left(), .left = cell_box.box_model().border.left == 0 ? CSS::BorderData() : cell_box.computed_values().border_left(),
}; };
auto cell_rect = cell_coordinates_to_device_rect.get({ cell_box.table_cell_coordinates()->row_index, cell_box.table_cell_coordinates()->column_index }).value(); auto cell_rect = cell_coordinates_to_device_rect.get({ cell_box.table_cell_coordinates()->row_index, cell_box.table_cell_coordinates()->column_index }).value();
paint_all_borders(context, cell_rect, cell_box.normalized_border_radii_data(), borders_data); paint_all_borders(context.painter(), cell_rect, cell_box.normalized_border_radii_data().as_corners(context), borders_data.to_device_pixels(context));
} }
void paint_table_borders(PaintContext& context, PaintableBox const& table_paintable) void paint_table_borders(PaintContext& context, PaintableBox const& table_paintable)
@ -436,7 +436,7 @@ void paint_table_borders(PaintContext& context, PaintableBox const& table_painta
.bottom = cell_box.box_model().border.bottom == 0 ? CSS::BorderData() : cell_box.computed_values().border_bottom(), .bottom = cell_box.box_model().border.bottom == 0 ? CSS::BorderData() : cell_box.computed_values().border_bottom(),
.left = cell_box.box_model().border.left == 0 ? CSS::BorderData() : cell_box.computed_values().border_left(), .left = cell_box.box_model().border.left == 0 ? CSS::BorderData() : cell_box.computed_values().border_left(),
}; };
paint_all_borders(context, context.rounded_device_rect(cell_box.absolute_border_box_rect()), cell_box.normalized_border_radii_data(), borders_data); paint_all_borders(context.painter(), context.rounded_device_rect(cell_box.absolute_border_box_rect()), cell_box.normalized_border_radii_data().as_corners(context), borders_data.to_device_pixels(context));
} }
} }
} }