1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 08:37:45 +00:00

LibWeb: Convert border painting to new pixel units

This commit is contained in:
Sam Atkins 2022-10-27 16:02:32 +01:00 committed by Linus Groh
parent 0233627545
commit 0bf4089af9
12 changed files with 135 additions and 140 deletions

View file

@ -77,7 +77,7 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet
Gfx::AntiAliasingPainter aa_painter { painter }; Gfx::AntiAliasingPainter aa_painter { painter };
aa_painter.fill_rect_with_rounded_corners(context.rounded_device_rect(color_box.rect).to_type<int>(), aa_painter.fill_rect_with_rounded_corners(context.rounded_device_rect(color_box.rect).to_type<int>(),
background_color, color_box.radii.top_left.as_corner(), color_box.radii.top_right.as_corner(), color_box.radii.bottom_right.as_corner(), color_box.radii.bottom_left.as_corner()); background_color, color_box.radii.top_left.as_corner(context), color_box.radii.top_right.as_corner(context), color_box.radii.bottom_right.as_corner(context), color_box.radii.bottom_left.as_corner(context));
if (!has_paintable_layers) if (!has_paintable_layers)
return; return;
@ -114,7 +114,7 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet
CSSPixelRect const& css_clip_rect = clip_box.rect; CSSPixelRect const& css_clip_rect = clip_box.rect;
auto clip_rect = context.rounded_device_rect(css_clip_rect); auto clip_rect = context.rounded_device_rect(css_clip_rect);
painter.add_clip_rect(clip_rect.to_type<int>()); painter.add_clip_rect(clip_rect.to_type<int>());
ScopedCornerRadiusClip corner_clip { painter, clip_rect.to_type<int>(), clip_box.radii }; ScopedCornerRadiusClip corner_clip { context, painter, clip_rect, clip_box.radii };
if (layer.clip == CSS::BackgroundBox::BorderBox) { if (layer.clip == CSS::BackgroundBox::BorderBox) {
// Shrink the effective clip rect if to account for the bits the borders will definitely paint over // Shrink the effective clip rect if to account for the bits the borders will definitely paint over

View file

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org> * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021, Sam Atkins <atkinssj@serenityos.org> * Copyright (c) 2021-2022, Sam Atkins <atkinssj@serenityos.org>
* Copyright (c) 2022, MacDue <macdue@dueutil.tech> * Copyright (c) 2022, MacDue <macdue@dueutil.tech>
* *
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
@ -14,7 +14,7 @@
namespace Web::Painting { namespace Web::Painting {
BorderRadiiData normalized_border_radii_data(Layout::Node const& node, Gfx::FloatRect const& rect, CSS::BorderRadiusData top_left_radius, CSS::BorderRadiusData top_right_radius, CSS::BorderRadiusData bottom_right_radius, CSS::BorderRadiusData bottom_left_radius) BorderRadiiData normalized_border_radii_data(Layout::Node const& node, CSSPixelRect const& rect, CSS::BorderRadiusData top_left_radius, CSS::BorderRadiusData top_right_radius, CSS::BorderRadiusData bottom_right_radius, CSS::BorderRadiusData bottom_left_radius)
{ {
BorderRadiusData bottom_left_radius_px {}; BorderRadiusData bottom_left_radius_px {};
BorderRadiusData bottom_right_radius_px {}; BorderRadiusData bottom_right_radius_px {};
@ -34,15 +34,15 @@ BorderRadiiData normalized_border_radii_data(Layout::Node const& node, Gfx::Floa
top_right_radius_px.vertical_radius = top_right_radius.vertical_radius.resolved(node, height_length).to_px(node); top_right_radius_px.vertical_radius = top_right_radius.vertical_radius.resolved(node, height_length).to_px(node);
// Scale overlapping curves according to https://www.w3.org/TR/css-backgrounds-3/#corner-overlap // Scale overlapping curves according to https://www.w3.org/TR/css-backgrounds-3/#corner-overlap
auto f = 1.0f; CSSPixels f = 1.0f;
auto width_reciprocal = 1.0f / rect.width(); auto width_reciprocal = 1.0f / rect.width().value();
auto height_reciprocal = 1.0f / rect.height(); auto height_reciprocal = 1.0f / rect.height().value();
f = max(f, width_reciprocal * (top_left_radius_px.horizontal_radius + top_right_radius_px.horizontal_radius)); f = max(f, width_reciprocal * (top_left_radius_px.horizontal_radius + top_right_radius_px.horizontal_radius));
f = max(f, height_reciprocal * (top_right_radius_px.vertical_radius + bottom_right_radius_px.vertical_radius)); f = max(f, height_reciprocal * (top_right_radius_px.vertical_radius + bottom_right_radius_px.vertical_radius));
f = max(f, width_reciprocal * (bottom_left_radius_px.horizontal_radius + bottom_right_radius_px.horizontal_radius)); f = max(f, width_reciprocal * (bottom_left_radius_px.horizontal_radius + bottom_right_radius_px.horizontal_radius));
f = max(f, height_reciprocal * (top_left_radius_px.vertical_radius + bottom_left_radius_px.vertical_radius)); f = max(f, height_reciprocal * (top_left_radius_px.vertical_radius + bottom_left_radius_px.vertical_radius));
f = 1.0f / f; f = 1.0f / f.value();
top_left_radius_px.horizontal_radius *= f; top_left_radius_px.horizontal_radius *= f;
top_left_radius_px.vertical_radius *= f; top_left_radius_px.vertical_radius *= f;
@ -56,7 +56,7 @@ BorderRadiiData normalized_border_radii_data(Layout::Node const& node, Gfx::Floa
return BorderRadiiData { top_left_radius_px, top_right_radius_px, bottom_right_radius_px, bottom_left_radius_px }; return BorderRadiiData { top_left_radius_px, top_right_radius_px, bottom_right_radius_px, bottom_left_radius_px };
} }
void paint_border(PaintContext& context, BorderEdge edge, Gfx::IntRect const& rect, BorderRadiiData const& border_radii_data, BordersData const& borders_data) void paint_border(PaintContext& context, BorderEdge edge, DevicePixelRect const& rect, BorderRadiiData const& border_radii_data, BordersData const& borders_data)
{ {
auto const& border_data = [&] { auto const& border_data = [&] {
switch (edge) { switch (edge) {
@ -71,20 +71,20 @@ void paint_border(PaintContext& context, BorderEdge edge, Gfx::IntRect const& re
} }
}(); }();
float width = border_data.width; CSSPixels width = border_data.width;
if (width <= 0) if (width <= 0)
return; return;
auto color = border_data.color; auto color = border_data.color;
auto border_style = border_data.line_style; auto border_style = border_data.line_style;
int int_width = ceilf(width); auto device_pixel_width = context.enclosing_device_pixels(width);
struct Points { struct Points {
Gfx::IntPoint p1; DevicePixelPoint p1;
Gfx::IntPoint p2; DevicePixelPoint p2;
}; };
auto points_for_edge = [](BorderEdge edge, Gfx::IntRect const& rect) -> Points { auto points_for_edge = [](BorderEdge edge, DevicePixelRect const& rect) -> Points {
switch (edge) { switch (edge) {
case BorderEdge::Top: case BorderEdge::Top:
return { rect.top_left(), rect.top_right() }; return { rect.top_left(), rect.top_right() };
@ -117,28 +117,28 @@ void paint_border(PaintContext& context, BorderEdge edge, Gfx::IntRect const& re
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(int_width / 2, int_width / 2); p1.translate_by(device_pixel_width / 2, device_pixel_width / 2);
p2.translate_by(-int_width / 2, int_width / 2); p2.translate_by(-device_pixel_width / 2, device_pixel_width / 2);
break; break;
case BorderEdge::Right: case BorderEdge::Right:
p1.translate_by(-int_width / 2, int_width / 2); p1.translate_by(-device_pixel_width / 2, device_pixel_width / 2);
p2.translate_by(-int_width / 2, -int_width / 2); p2.translate_by(-device_pixel_width / 2, -device_pixel_width / 2);
break; break;
case BorderEdge::Bottom: case BorderEdge::Bottom:
p1.translate_by(int_width / 2, -int_width / 2); p1.translate_by(device_pixel_width / 2, -device_pixel_width / 2);
p2.translate_by(-int_width / 2, -int_width / 2); p2.translate_by(-device_pixel_width / 2, -device_pixel_width / 2);
break; break;
case BorderEdge::Left: case BorderEdge::Left:
p1.translate_by(int_width / 2, int_width / 2); p1.translate_by(device_pixel_width / 2, device_pixel_width / 2);
p2.translate_by(int_width / 2, -int_width / 2); p2.translate_by(device_pixel_width / 2, -device_pixel_width / 2);
break; break;
} }
if (border_style == CSS::LineStyle::Dotted) { if (border_style == CSS::LineStyle::Dotted) {
Gfx::AntiAliasingPainter aa_painter { context.painter() }; Gfx::AntiAliasingPainter aa_painter { context.painter() };
aa_painter.draw_line(p1.to_type<float>(), p2.to_type<float>(), color, int_width, gfx_line_style); aa_painter.draw_line(p1.to_type<int>(), p2.to_type<int>(), color, device_pixel_width.value(), gfx_line_style);
return; return;
} }
context.painter().draw_line(p1, p2, color, int_width, gfx_line_style); context.painter().draw_line(p1.to_type<int>(), p2.to_type<int>(), color, device_pixel_width.value(), gfx_line_style);
return; return;
} }
@ -146,19 +146,17 @@ void paint_border(PaintContext& context, BorderEdge edge, Gfx::IntRect const& re
// Note: Using fill_rect() here since draw_line() produces some overlapping pixels // Note: Using fill_rect() here since draw_line() produces some overlapping pixels
// at the end of a line, which cause issues on borders with transparency. // at the end of a line, which cause issues on borders with transparency.
p2.translate_by(1, 1); p2.translate_by(1, 1);
context.painter().fill_rect(Gfx::IntRect::from_two_points(p1, p2), color); context.painter().fill_rect(Gfx::IntRect::from_two_points(p1.template to_type<int>(), p2.template to_type<int>()), color);
}; };
auto draw_border = [&](auto const& border, auto const& radius, auto const& opposite_border, auto const& opposite_radius, auto p1_step_translate, auto p2_step_translate) { auto draw_border = [&](auto const& border, auto const& radius, auto const& opposite_border, auto const& opposite_radius, auto p1_step_translate, auto p2_step_translate) {
auto [p1, p2] = points_for_edge(edge, rect); auto [p1, p2] = points_for_edge(edge, rect);
auto current_p1 = p1.to_type<float>(); auto p1_step = radius ? 0 : border.width / static_cast<float>(device_pixel_width.value());
auto current_p2 = p2.to_type<float>(); auto p2_step = opposite_radius ? 0 : opposite_border.width / static_cast<float>(device_pixel_width.value());
auto p1_step = radius ? 0 : border.width / static_cast<float>(int_width); for (DevicePixels i = 0; i < device_pixel_width; ++i) {
auto p2_step = opposite_radius ? 0 : opposite_border.width / static_cast<float>(int_width); draw_horizontal_or_vertical_line(p1, p2);
for (int i = 0; i < int_width; ++i) { p1_step_translate(p1, p1_step);
draw_horizontal_or_vertical_line(current_p1.to_type<int>(), current_p2.to_type<int>()); p2_step_translate(p2, p2_step);
p1_step_translate(current_p1, p1_step);
p2_step_translate(current_p2, p2_step);
} }
}; };
@ -209,10 +207,10 @@ void paint_border(PaintContext& context, BorderEdge edge, Gfx::IntRect const& re
} }
} }
RefPtr<Gfx::Bitmap> get_cached_corner_bitmap(Gfx::IntSize corners_size) RefPtr<Gfx::Bitmap> get_cached_corner_bitmap(DevicePixelSize corners_size)
{ {
auto allocate_mask_bitmap = [&]() -> RefPtr<Gfx::Bitmap> { auto allocate_mask_bitmap = [&]() -> RefPtr<Gfx::Bitmap> {
auto bitmap = Gfx::Bitmap::try_create(Gfx::BitmapFormat::BGRA8888, corners_size); auto bitmap = Gfx::Bitmap::try_create(Gfx::BitmapFormat::BGRA8888, corners_size.to_type<int>());
if (!bitmap.is_error()) if (!bitmap.is_error())
return bitmap.release_value(); return bitmap.release_value();
return nullptr; return nullptr;
@ -221,7 +219,7 @@ RefPtr<Gfx::Bitmap> get_cached_corner_bitmap(Gfx::IntSize corners_size)
static thread_local auto corner_bitmap = allocate_mask_bitmap(); static thread_local auto corner_bitmap = allocate_mask_bitmap();
// Only reallocate the corner bitmap is the existing one is too small. // Only reallocate the corner bitmap is the existing one is too small.
// (should mean no more allocations after the first paint -- amortised zero allocations :^)) // (should mean no more allocations after the first paint -- amortised zero allocations :^))
if (corner_bitmap && corner_bitmap->rect().size().contains(corners_size)) { if (corner_bitmap && corner_bitmap->rect().size().contains(corners_size.to_type<int>())) {
Gfx::Painter painter { *corner_bitmap }; Gfx::Painter painter { *corner_bitmap };
painter.clear_rect({ { 0, 0 }, corners_size }, Gfx::Color()); painter.clear_rect({ { 0, 0 }, corners_size }, Gfx::Color());
} else { } else {
@ -234,17 +232,17 @@ RefPtr<Gfx::Bitmap> get_cached_corner_bitmap(Gfx::IntSize corners_size)
return corner_bitmap; return corner_bitmap;
} }
void paint_all_borders(PaintContext& context, Gfx::FloatRect const& bordered_rect, BorderRadiiData const& border_radii_data, BordersData const& borders_data) void paint_all_borders(PaintContext& context, CSSPixelRect const& bordered_rect, BorderRadiiData const& border_radii_data, BordersData 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;
Gfx::IntRect border_rect = bordered_rect.to_rounded<int>(); auto border_rect = context.rounded_device_rect(bordered_rect);
auto top_left = border_radii_data.top_left.as_corner(); auto top_left = border_radii_data.top_left.as_corner(context);
auto top_right = border_radii_data.top_right.as_corner(); auto top_right = border_radii_data.top_right.as_corner(context);
auto bottom_right = border_radii_data.bottom_right.as_corner(); auto bottom_right = border_radii_data.bottom_right.as_corner(context);
auto bottom_left = border_radii_data.bottom_left.as_corner(); auto bottom_left = border_radii_data.bottom_left.as_corner(context);
// 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)
@ -256,32 +254,28 @@ void paint_all_borders(PaintContext& context, Gfx::FloatRect const& bordered_rec
if (borders_data.top.width <= 0 && borders_data.right.width <= 0) if (borders_data.top.width <= 0 && borders_data.right.width <= 0)
top_right = { 0, 0 }; top_right = { 0, 0 };
auto int_width = [&](auto value) -> int { DevicePixelRect top_border_rect = {
return ceilf(value);
};
Gfx::IntRect top_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,
int_width(borders_data.top.width) context.enclosing_device_pixels(borders_data.top.width)
}; };
Gfx::IntRect right_border_rect = { DevicePixelRect right_border_rect = {
border_rect.x() + (border_rect.width() - int_width(borders_data.right.width)), border_rect.x() + (border_rect.width() - context.enclosing_device_pixels(borders_data.right.width)),
border_rect.y() + top_right.vertical_radius, border_rect.y() + top_right.vertical_radius,
int_width(borders_data.right.width), context.enclosing_device_pixels(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
}; };
Gfx::IntRect 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() - int_width(borders_data.bottom.width)), border_rect.y() + (border_rect.height() - context.enclosing_device_pixels(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,
int_width(borders_data.bottom.width) context.enclosing_device_pixels(borders_data.bottom.width)
}; };
Gfx::IntRect 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,
int_width(borders_data.left.width), context.enclosing_device_pixels(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
}; };
@ -308,16 +302,16 @@ void paint_all_borders(PaintContext& context, Gfx::FloatRect const& bordered_rec
return; return;
// Cache the smallest possible bitmap to render just the corners for the border. // Cache the smallest possible bitmap to render just the corners for the border.
auto expand_width = abs(int_width(borders_data.left.width) - int_width(borders_data.right.width)); auto expand_width = abs(context.enclosing_device_pixels(borders_data.left.width) - context.enclosing_device_pixels(borders_data.right.width));
auto expand_height = abs(int_width(borders_data.top.width) - int_width(borders_data.bottom.width)); auto expand_height = abs(context.enclosing_device_pixels(borders_data.top.width) - context.enclosing_device_pixels(borders_data.bottom.width));
Gfx::IntRect corner_mask_rect { DevicePixelRect corner_mask_rect {
0, 0, 0, 0,
max( max(
top_left.horizontal_radius + top_right.horizontal_radius + expand_width, top_left.horizontal_radius + top_right.horizontal_radius + expand_width.value(),
bottom_left.horizontal_radius + bottom_right.horizontal_radius + expand_height), bottom_left.horizontal_radius + bottom_right.horizontal_radius + expand_height.value()),
max( max(
top_left.vertical_radius + bottom_left.vertical_radius + expand_width, top_left.vertical_radius + bottom_left.vertical_radius + expand_width.value(),
top_right.vertical_radius + bottom_right.vertical_radius + expand_height) top_right.vertical_radius + bottom_right.vertical_radius + expand_height.value())
}; };
auto corner_bitmap = get_cached_corner_bitmap(corner_mask_rect.size()); auto corner_bitmap = get_cached_corner_bitmap(corner_mask_rect.size());
@ -331,27 +325,27 @@ void paint_all_borders(PaintContext& context, Gfx::FloatRect const& bordered_rec
// TODO: Support various line styles on the corners (dotted, dashes, etc) // TODO: Support various line styles on the corners (dotted, dashes, etc)
// Paint the outer (minimal) corner rounded rectangle: // Paint the outer (minimal) corner rounded rectangle:
aa_painter.fill_rect_with_rounded_corners(corner_mask_rect, border_color_no_alpha, top_left, top_right, bottom_right, bottom_left); aa_painter.fill_rect_with_rounded_corners(corner_mask_rect.to_type<int>(), border_color_no_alpha, top_left, top_right, bottom_right, bottom_left);
// Subtract the inner corner rectangle: // Subtract the inner corner rectangle:
auto inner_corner_mask_rect = corner_mask_rect.shrunken( auto inner_corner_mask_rect = corner_mask_rect.shrunken(
int_width(borders_data.top.width), context.enclosing_device_pixels(borders_data.top.width),
int_width(borders_data.right.width), context.enclosing_device_pixels(borders_data.right.width),
int_width(borders_data.bottom.width), context.enclosing_device_pixels(borders_data.bottom.width),
int_width(borders_data.left.width)); context.enclosing_device_pixels(borders_data.left.width));
auto inner_top_left = top_left; auto inner_top_left = top_left;
auto inner_top_right = top_right; auto inner_top_right = top_right;
auto inner_bottom_right = bottom_right; auto inner_bottom_right = bottom_right;
auto inner_bottom_left = bottom_left; auto inner_bottom_left = bottom_left;
inner_top_left.horizontal_radius = max(0, inner_top_left.horizontal_radius - int_width(borders_data.left.width)); inner_top_left.horizontal_radius = max(0, inner_top_left.horizontal_radius - context.enclosing_device_pixels(borders_data.left.width).value());
inner_top_left.vertical_radius = max(0, inner_top_left.vertical_radius - int_width(borders_data.top.width)); inner_top_left.vertical_radius = max(0, inner_top_left.vertical_radius - context.enclosing_device_pixels(borders_data.top.width).value());
inner_top_right.horizontal_radius = max(0, inner_top_right.horizontal_radius - int_width(borders_data.right.width)); inner_top_right.horizontal_radius = max(0, inner_top_right.horizontal_radius - context.enclosing_device_pixels(borders_data.right.width).value());
inner_top_right.vertical_radius = max(0, inner_top_right.vertical_radius - int_width(borders_data.top.width)); inner_top_right.vertical_radius = max(0, inner_top_right.vertical_radius - context.enclosing_device_pixels(borders_data.top.width).value());
inner_bottom_right.horizontal_radius = max(0, inner_bottom_right.horizontal_radius - int_width(borders_data.right.width)); inner_bottom_right.horizontal_radius = max(0, inner_bottom_right.horizontal_radius - context.enclosing_device_pixels(borders_data.right.width).value());
inner_bottom_right.vertical_radius = max(0, inner_bottom_right.vertical_radius - int_width(borders_data.bottom.width)); inner_bottom_right.vertical_radius = max(0, inner_bottom_right.vertical_radius - context.enclosing_device_pixels(borders_data.bottom.width).value());
inner_bottom_left.horizontal_radius = max(0, inner_bottom_left.horizontal_radius - int_width(borders_data.left.width)); inner_bottom_left.horizontal_radius = max(0, inner_bottom_left.horizontal_radius - context.enclosing_device_pixels(borders_data.left.width).value());
inner_bottom_left.vertical_radius = max(0, inner_bottom_left.vertical_radius - int_width(borders_data.bottom.width)); inner_bottom_left.vertical_radius = max(0, inner_bottom_left.vertical_radius - context.enclosing_device_pixels(borders_data.bottom.width).value());
aa_painter.fill_rect_with_rounded_corners(inner_corner_mask_rect, border_color_no_alpha, inner_top_left, inner_top_right, inner_bottom_right, inner_bottom_left, Gfx::AntiAliasingPainter::BlendMode::AlphaSubtract); aa_painter.fill_rect_with_rounded_corners(inner_corner_mask_rect.to_type<int>(), border_color_no_alpha, inner_top_left, inner_top_right, inner_bottom_right, inner_bottom_left, Gfx::AntiAliasingPainter::BlendMode::AlphaSubtract);
// TODO: Support dual color corners. Other browsers will render a rounded corner between two borders of // TODO: Support dual color corners. Other browsers will render a rounded corner between two borders of
// different colors using both colours, normally split at a 45 degree angle (though the exact angle is interpolated). // different colors using both colours, normally split at a 45 degree angle (though the exact angle is interpolated).
@ -370,16 +364,16 @@ void paint_all_borders(PaintContext& context, Gfx::FloatRect const& bordered_rec
// Blit the corners into to their corresponding locations: // Blit the corners into to their corresponding locations:
if (top_left) if (top_left)
blit_corner(border_rect.top_left(), top_left.as_rect(), pick_corner_color(borders_data.top, borders_data.left)); blit_corner(border_rect.top_left().to_type<int>(), top_left.as_rect(), pick_corner_color(borders_data.top, borders_data.left));
if (top_right) if (top_right)
blit_corner(border_rect.top_right().translated(-top_right.horizontal_radius + 1, 0), top_right.as_rect().translated(corner_mask_rect.width() - top_right.horizontal_radius, 0), pick_corner_color(borders_data.top, borders_data.right)); blit_corner(border_rect.top_right().to_type<int>().translated(-top_right.horizontal_radius + 1, 0), top_right.as_rect().translated(corner_mask_rect.width().value() - top_right.horizontal_radius, 0), pick_corner_color(borders_data.top, borders_data.right));
if (bottom_right) if (bottom_right)
blit_corner(border_rect.bottom_right().translated(-bottom_right.horizontal_radius + 1, -bottom_right.vertical_radius + 1), bottom_right.as_rect().translated(corner_mask_rect.width() - bottom_right.horizontal_radius, corner_mask_rect.height() - bottom_right.vertical_radius), pick_corner_color(borders_data.bottom, borders_data.right)); blit_corner(border_rect.bottom_right().to_type<int>().translated(-bottom_right.horizontal_radius + 1, -bottom_right.vertical_radius + 1), bottom_right.as_rect().translated(corner_mask_rect.width().value() - bottom_right.horizontal_radius, corner_mask_rect.height().value() - bottom_right.vertical_radius), pick_corner_color(borders_data.bottom, borders_data.right));
if (bottom_left) if (bottom_left)
blit_corner(border_rect.bottom_left().translated(0, -bottom_left.vertical_radius + 1), bottom_left.as_rect().translated(0, corner_mask_rect.height() - bottom_left.vertical_radius), pick_corner_color(borders_data.bottom, borders_data.left)); blit_corner(border_rect.bottom_left().to_type<int>().translated(0, -bottom_left.vertical_radius + 1), bottom_left.as_rect().translated(0, corner_mask_rect.height().value() - bottom_left.vertical_radius), pick_corner_color(borders_data.bottom, borders_data.left));
} }
} }

View file

@ -13,26 +13,26 @@
namespace Web::Painting { namespace Web::Painting {
struct BorderRadiusData { struct BorderRadiusData {
float horizontal_radius { 0 }; CSSPixels horizontal_radius { 0 };
float vertical_radius { 0 }; CSSPixels vertical_radius { 0 };
Gfx::AntiAliasingPainter::CornerRadius as_corner() const Gfx::AntiAliasingPainter::CornerRadius as_corner(PaintContext& context) const
{ {
return Gfx::AntiAliasingPainter::CornerRadius { return Gfx::AntiAliasingPainter::CornerRadius {
static_cast<int>(horizontal_radius), context.floored_device_pixels(horizontal_radius).value(),
static_cast<int>(vertical_radius) context.floored_device_pixels(vertical_radius).value()
}; };
}; };
inline operator bool() const inline operator bool() const
{ {
return static_cast<int>(horizontal_radius) > 0 && static_cast<int>(vertical_radius) > 0; return horizontal_radius > 0 && vertical_radius > 0;
} }
inline void shrink(float horizontal, float vertical) inline void shrink(CSSPixels horizontal, CSSPixels vertical)
{ {
horizontal_radius = max(0, horizontal_radius - horizontal); horizontal_radius = max(CSSPixels(0), horizontal_radius - horizontal);
vertical_radius = max(0, vertical_radius - vertical); vertical_radius = max(CSSPixels(0), vertical_radius - vertical);
} }
}; };
@ -47,7 +47,7 @@ struct BorderRadiiData {
return top_left || top_right || bottom_right || bottom_left; return top_left || top_right || bottom_right || bottom_left;
} }
inline void shrink(float top, float right, float bottom, float left) inline void shrink(CSSPixels top, CSSPixels right, CSSPixels bottom, CSSPixels left)
{ {
top_left.shrink(left, top); top_left.shrink(left, top);
top_right.shrink(right, top); top_right.shrink(right, top);
@ -56,7 +56,7 @@ struct BorderRadiiData {
} }
}; };
BorderRadiiData normalized_border_radii_data(Layout::Node const&, Gfx::FloatRect const&, CSS::BorderRadiusData top_left_radius, CSS::BorderRadiusData top_right_radius, CSS::BorderRadiusData bottom_right_radius, CSS::BorderRadiusData bottom_left_radius); BorderRadiiData normalized_border_radii_data(Layout::Node const&, CSSPixelRect const&, CSS::BorderRadiusData top_left_radius, CSS::BorderRadiusData top_right_radius, CSS::BorderRadiusData bottom_right_radius, CSS::BorderRadiusData bottom_left_radius);
enum class BorderEdge { enum class BorderEdge {
Top, Top,
@ -71,9 +71,9 @@ struct BordersData {
CSS::BorderData left; CSS::BorderData left;
}; };
RefPtr<Gfx::Bitmap> get_cached_corner_bitmap(Gfx::IntSize corners_size); RefPtr<Gfx::Bitmap> get_cached_corner_bitmap(DevicePixelSize corners_size);
void paint_border(PaintContext& context, BorderEdge edge, Gfx::IntRect const& rect, BorderRadiiData const& border_radii_data, BordersData const& borders_data); void paint_border(PaintContext& context, BorderEdge edge, DevicePixelRect const& rect, BorderRadiiData const& border_radii_data, BordersData const& borders_data);
void paint_all_borders(PaintContext& context, Gfx::FloatRect const& bordered_rect, BorderRadiiData const& border_radii_data, BordersData const&); void paint_all_borders(PaintContext& context, CSSPixelRect const& bordered_rect, BorderRadiiData const& border_radii_data, BordersData const&);
} }

View file

@ -10,16 +10,16 @@
namespace Web::Painting { namespace Web::Painting {
ErrorOr<BorderRadiusCornerClipper> BorderRadiusCornerClipper::create(Gfx::IntRect const& border_rect, BorderRadiiData const& border_radii, CornerClip corner_clip, UseCachedBitmap use_cached_bitmap) ErrorOr<BorderRadiusCornerClipper> BorderRadiusCornerClipper::create(PaintContext& context, DevicePixelRect const& border_rect, BorderRadiiData const& border_radii, CornerClip corner_clip, UseCachedBitmap use_cached_bitmap)
{ {
VERIFY(border_radii.has_any_radius()); VERIFY(border_radii.has_any_radius());
auto top_left = border_radii.top_left.as_corner(); auto top_left = border_radii.top_left.as_corner(context);
auto top_right = border_radii.top_right.as_corner(); auto top_right = border_radii.top_right.as_corner(context);
auto bottom_right = border_radii.bottom_right.as_corner(); auto bottom_right = border_radii.bottom_right.as_corner(context);
auto bottom_left = border_radii.bottom_left.as_corner(); auto bottom_left = border_radii.bottom_left.as_corner(context);
Gfx::IntSize corners_bitmap_size { DevicePixelSize corners_bitmap_size {
max( max(
top_left.horizontal_radius + top_right.horizontal_radius, top_left.horizontal_radius + top_right.horizontal_radius,
bottom_left.horizontal_radius + bottom_right.horizontal_radius), bottom_left.horizontal_radius + bottom_right.horizontal_radius),
@ -34,7 +34,7 @@ ErrorOr<BorderRadiusCornerClipper> BorderRadiusCornerClipper::create(Gfx::IntRec
if (!corner_bitmap) if (!corner_bitmap)
return Error::from_errno(ENOMEM); return Error::from_errno(ENOMEM);
} else { } else {
corner_bitmap = TRY(Gfx::Bitmap::try_create(Gfx::BitmapFormat::BGRA8888, corners_bitmap_size)); corner_bitmap = TRY(Gfx::Bitmap::try_create(Gfx::BitmapFormat::BGRA8888, corners_bitmap_size.to_type<int>()));
} }
CornerData corner_data { CornerData corner_data {
@ -60,7 +60,7 @@ void BorderRadiusCornerClipper::sample_under_corners(Gfx::Painter& page_painter)
corner_aa_painter.fill_rect_with_rounded_corners(corner_rect, Color::NamedColor::Black, corner_aa_painter.fill_rect_with_rounded_corners(corner_rect, Color::NamedColor::Black,
m_data.corner_radii.top_left, m_data.corner_radii.top_right, m_data.corner_radii.bottom_right, m_data.corner_radii.bottom_left); m_data.corner_radii.top_left, m_data.corner_radii.top_right, m_data.corner_radii.bottom_right, m_data.corner_radii.bottom_left);
auto copy_page_masked = [&](auto const& mask_src, auto const& page_location) { auto copy_page_masked = [&](Gfx::IntRect const& mask_src, Gfx::IntPoint const& page_location) {
for (int row = 0; row < mask_src.height(); ++row) { for (int row = 0; row < mask_src.height(); ++row) {
for (int col = 0; col < mask_src.width(); ++col) { for (int col = 0; col < mask_src.width(); ++col) {
auto corner_location = mask_src.location().translated(col, row); auto corner_location = mask_src.location().translated(col, row);
@ -81,13 +81,13 @@ void BorderRadiusCornerClipper::sample_under_corners(Gfx::Painter& page_painter)
// Copy the pixels under the corner mask (using the alpha of the mask): // Copy the pixels under the corner mask (using the alpha of the mask):
if (m_data.corner_radii.top_left) if (m_data.corner_radii.top_left)
copy_page_masked(m_data.corner_radii.top_left.as_rect().translated(m_data.bitmap_locations.top_left), m_data.page_locations.top_left); copy_page_masked(m_data.corner_radii.top_left.as_rect().translated(m_data.bitmap_locations.top_left.to_type<int>()), m_data.page_locations.top_left.to_type<int>());
if (m_data.corner_radii.top_right) if (m_data.corner_radii.top_right)
copy_page_masked(m_data.corner_radii.top_right.as_rect().translated(m_data.bitmap_locations.top_right), m_data.page_locations.top_right); copy_page_masked(m_data.corner_radii.top_right.as_rect().translated(m_data.bitmap_locations.top_right.to_type<int>()), m_data.page_locations.top_right.to_type<int>());
if (m_data.corner_radii.bottom_right) if (m_data.corner_radii.bottom_right)
copy_page_masked(m_data.corner_radii.bottom_right.as_rect().translated(m_data.bitmap_locations.bottom_right), m_data.page_locations.bottom_right); copy_page_masked(m_data.corner_radii.bottom_right.as_rect().translated(m_data.bitmap_locations.bottom_right.to_type<int>()), m_data.page_locations.bottom_right.to_type<int>());
if (m_data.corner_radii.bottom_left) if (m_data.corner_radii.bottom_left)
copy_page_masked(m_data.corner_radii.bottom_left.as_rect().translated(m_data.bitmap_locations.bottom_left), m_data.page_locations.bottom_left); copy_page_masked(m_data.corner_radii.bottom_left.as_rect().translated(m_data.bitmap_locations.bottom_left.to_type<int>()), m_data.page_locations.bottom_left.to_type<int>());
m_has_sampled = true; m_has_sampled = true;
} }
@ -98,13 +98,13 @@ void BorderRadiusCornerClipper::blit_corner_clipping(Gfx::Painter& painter)
// Restore the corners: // Restore the corners:
if (m_data.corner_radii.top_left) if (m_data.corner_radii.top_left)
painter.blit(m_data.page_locations.top_left, *m_corner_bitmap, m_data.corner_radii.top_left.as_rect().translated(m_data.bitmap_locations.top_left)); painter.blit(m_data.page_locations.top_left.to_type<int>(), *m_corner_bitmap, m_data.corner_radii.top_left.as_rect().translated(m_data.bitmap_locations.top_left.to_type<int>()));
if (m_data.corner_radii.top_right) if (m_data.corner_radii.top_right)
painter.blit(m_data.page_locations.top_right, *m_corner_bitmap, m_data.corner_radii.top_right.as_rect().translated(m_data.bitmap_locations.top_right)); painter.blit(m_data.page_locations.top_right.to_type<int>(), *m_corner_bitmap, m_data.corner_radii.top_right.as_rect().translated(m_data.bitmap_locations.top_right.to_type<int>()));
if (m_data.corner_radii.bottom_right) if (m_data.corner_radii.bottom_right)
painter.blit(m_data.page_locations.bottom_right, *m_corner_bitmap, m_data.corner_radii.bottom_right.as_rect().translated(m_data.bitmap_locations.bottom_right)); painter.blit(m_data.page_locations.bottom_right.to_type<int>(), *m_corner_bitmap, m_data.corner_radii.bottom_right.as_rect().translated(m_data.bitmap_locations.bottom_right.to_type<int>()));
if (m_data.corner_radii.bottom_left) if (m_data.corner_radii.bottom_left)
painter.blit(m_data.page_locations.bottom_left, *m_corner_bitmap, m_data.corner_radii.bottom_left.as_rect().translated(m_data.bitmap_locations.bottom_left)); painter.blit(m_data.page_locations.bottom_left.to_type<int>(), *m_corner_bitmap, m_data.corner_radii.bottom_left.as_rect().translated(m_data.bitmap_locations.bottom_left.to_type<int>()));
} }
} }

View file

@ -23,7 +23,7 @@ public:
No No
}; };
static ErrorOr<BorderRadiusCornerClipper> create(Gfx::IntRect const& border_rect, BorderRadiiData const& border_radii, CornerClip corner_clip = CornerClip::Outside, UseCachedBitmap use_cached_bitmap = UseCachedBitmap::Yes); static ErrorOr<BorderRadiusCornerClipper> create(PaintContext&, DevicePixelRect const& border_rect, BorderRadiiData const& border_radii, CornerClip corner_clip = CornerClip::Outside, UseCachedBitmap use_cached_bitmap = UseCachedBitmap::Yes);
void sample_under_corners(Gfx::Painter& page_painter); void sample_under_corners(Gfx::Painter& page_painter);
void blit_corner_clipping(Gfx::Painter& page_painter); void blit_corner_clipping(Gfx::Painter& page_painter);
@ -38,14 +38,14 @@ private:
CornerRadius bottom_left; CornerRadius bottom_left;
} corner_radii; } corner_radii;
struct CornerLocations { struct CornerLocations {
Gfx::IntPoint top_left; DevicePixelPoint top_left;
Gfx::IntPoint top_right; DevicePixelPoint top_right;
Gfx::IntPoint bottom_right; DevicePixelPoint bottom_right;
Gfx::IntPoint bottom_left; DevicePixelPoint bottom_left;
}; };
CornerLocations page_locations; CornerLocations page_locations;
CornerLocations bitmap_locations; CornerLocations bitmap_locations;
Gfx::IntSize corner_bitmap_size; DevicePixelSize corner_bitmap_size;
} m_data; } m_data;
NonnullRefPtr<Gfx::Bitmap> m_corner_bitmap; NonnullRefPtr<Gfx::Bitmap> m_corner_bitmap;
@ -61,11 +61,11 @@ private:
}; };
struct ScopedCornerRadiusClip { struct ScopedCornerRadiusClip {
ScopedCornerRadiusClip(Gfx::Painter& painter, Gfx::IntRect const& border_rect, BorderRadiiData const& border_radii, CornerClip corner_clip = CornerClip::Outside, BorderRadiusCornerClipper::UseCachedBitmap use_cached_bitmap = BorderRadiusCornerClipper::UseCachedBitmap::Yes) ScopedCornerRadiusClip(PaintContext& context, Gfx::Painter& painter, DevicePixelRect const& border_rect, BorderRadiiData const& border_radii, CornerClip corner_clip = CornerClip::Outside, BorderRadiusCornerClipper::UseCachedBitmap use_cached_bitmap = BorderRadiusCornerClipper::UseCachedBitmap::Yes)
: m_painter(painter) : m_painter(painter)
{ {
if (border_radii.has_any_radius()) { if (border_radii.has_any_radius()) {
auto clipper = BorderRadiusCornerClipper::create(border_rect, border_radii, corner_clip, use_cached_bitmap); auto clipper = BorderRadiusCornerClipper::create(context, border_rect, border_radii, corner_clip, use_cached_bitmap);
if (!clipper.is_error()) { if (!clipper.is_error()) {
m_corner_clipper = clipper.release_value(); m_corner_clipper = clipper.release_value();
m_corner_clipper->sample_under_corners(m_painter); m_corner_clipper->sample_under_corners(m_painter);

View file

@ -31,8 +31,8 @@ void CanvasPaintable::paint(PaintContext& context, PaintPhase phase) const
PaintableBox::paint(context, phase); PaintableBox::paint(context, phase);
if (phase == PaintPhase::Foreground) { if (phase == PaintPhase::Foreground) {
auto canvas_rect = absolute_rect().to_rounded<int>(); auto canvas_rect = context.rounded_device_rect(absolute_rect().to_type<CSSPixels>());
ScopedCornerRadiusClip corner_clip { context.painter(), canvas_rect, normalized_border_radii_data(ShrinkRadiiForBorders::Yes) }; ScopedCornerRadiusClip corner_clip { context, context.painter(), canvas_rect, normalized_border_radii_data(ShrinkRadiiForBorders::Yes) };
// FIXME: This should be done at a different level. // FIXME: This should be done at a different level.
if (is_out_of_view(context)) if (is_out_of_view(context))
@ -41,7 +41,7 @@ void CanvasPaintable::paint(PaintContext& context, PaintPhase phase) const
if (layout_box().dom_node().bitmap()) { if (layout_box().dom_node().bitmap()) {
// FIXME: Remove this const_cast. // FIXME: Remove this const_cast.
const_cast<HTML::HTMLCanvasElement&>(layout_box().dom_node()).present(); const_cast<HTML::HTMLCanvasElement&>(layout_box().dom_node()).present();
context.painter().draw_scaled_bitmap(canvas_rect, *layout_box().dom_node().bitmap(), layout_box().dom_node().bitmap()->rect(), 1.0f, to_gfx_scaling_mode(computed_values().image_rendering())); context.painter().draw_scaled_bitmap(canvas_rect.to_type<int>(), *layout_box().dom_node().bitmap(), layout_box().dom_node().bitmap()->rect(), 1.0f, to_gfx_scaling_mode(computed_values().image_rendering()));
} }
} }
} }

View file

@ -125,7 +125,7 @@ void apply_backdrop_filter(PaintContext& context, Layout::Node const& node, Gfx:
// FIXME: 3. If element B has any transforms (between B and the Backdrop Root), apply the inverse of those transforms to the contents of T. // FIXME: 3. If element B has any transforms (between B and the Backdrop Root), apply the inverse of those transforms to the contents of T.
// 4. Apply a clip to the contents of T, using the border box of element B, including border-radius if specified. Note that the children of B are not considered for the sizing or location of this clip. // 4. Apply a clip to the contents of T, using the border box of element B, including border-radius if specified. Note that the children of B are not considered for the sizing or location of this clip.
ScopedCornerRadiusClip corner_clipper { context.painter(), backdrop_region, border_radii_data }; ScopedCornerRadiusClip corner_clipper { context, context.painter(), backdrop_region.to_type<DevicePixels>(), border_radii_data };
// FIXME: 5. Draw all of element B, including its background, border, and any children elements, into T. // FIXME: 5. Draw all of element B, including its background, border, and any children elements, into T.

View file

@ -49,9 +49,9 @@ void ImagePaintable::paint(PaintContext& context, PaintPhase phase) const
alt = image_element.src(); alt = image_element.src();
context.painter().draw_text(enclosing_int_rect(absolute_rect()), alt, Gfx::TextAlignment::Center, computed_values().color(), Gfx::TextElision::Right); context.painter().draw_text(enclosing_int_rect(absolute_rect()), alt, Gfx::TextAlignment::Center, computed_values().color(), Gfx::TextElision::Right);
} else if (auto bitmap = layout_box().image_loader().bitmap(layout_box().image_loader().current_frame_index())) { } else if (auto bitmap = layout_box().image_loader().bitmap(layout_box().image_loader().current_frame_index())) {
auto image_rect = absolute_rect().to_rounded<int>(); auto image_rect = context.rounded_device_rect(absolute_rect().to_type<CSSPixels>());
ScopedCornerRadiusClip corner_clip { context.painter(), image_rect, normalized_border_radii_data(ShrinkRadiiForBorders::Yes) }; ScopedCornerRadiusClip corner_clip { context, context.painter(), image_rect, normalized_border_radii_data(ShrinkRadiiForBorders::Yes) };
context.painter().draw_scaled_bitmap(image_rect, *bitmap, bitmap->rect(), 1.0f, to_gfx_scaling_mode(computed_values().image_rendering())); context.painter().draw_scaled_bitmap(image_rect.to_type<int>(), *bitmap, bitmap->rect(), 1.0f, to_gfx_scaling_mode(computed_values().image_rendering()));
} }
} }
} }

View file

@ -54,7 +54,7 @@ void InlinePaintable::paint(PaintContext& context, Painting::PaintPhase phase) c
absolute_fragment_rect.set_width(absolute_fragment_rect.width() + extra_end_width); absolute_fragment_rect.set_width(absolute_fragment_rect.width() + extra_end_width);
} }
auto border_radii_data = Painting::normalized_border_radii_data(layout_node(), absolute_fragment_rect, top_left_border_radius, top_right_border_radius, bottom_right_border_radius, bottom_left_border_radius); auto border_radii_data = Painting::normalized_border_radii_data(layout_node(), absolute_fragment_rect.to_type<CSSPixels>(), top_left_border_radius, top_right_border_radius, bottom_right_border_radius, bottom_left_border_radius);
Painting::paint_background(context, layout_node(), absolute_fragment_rect.to_type<CSSPixels>(), computed_values().background_color(), computed_values().image_rendering(), &computed_values().background_layers(), border_radii_data); Painting::paint_background(context, layout_node(), absolute_fragment_rect.to_type<CSSPixels>(), computed_values().background_color(), computed_values().image_rendering(), &computed_values().background_layers(), border_radii_data);
if (auto computed_box_shadow = computed_values().box_shadow(); !computed_box_shadow.is_empty()) { if (auto computed_box_shadow = computed_values().box_shadow(); !computed_box_shadow.is_empty()) {
@ -92,7 +92,7 @@ void InlinePaintable::paint(PaintContext& context, Painting::PaintPhase phase) c
auto containing_block_position_in_absolute_coordinates = containing_block()->paint_box()->absolute_position(); auto containing_block_position_in_absolute_coordinates = containing_block()->paint_box()->absolute_position();
for_each_fragment([&](auto const& fragment, bool is_first_fragment, bool is_last_fragment) { for_each_fragment([&](auto const& fragment, bool is_first_fragment, bool is_last_fragment) {
Gfx::FloatRect absolute_fragment_rect { containing_block_position_in_absolute_coordinates.translated(fragment.offset()), fragment.size() }; CSSPixelRect absolute_fragment_rect { containing_block_position_in_absolute_coordinates.translated(fragment.offset()), fragment.size() };
if (is_first_fragment) { if (is_first_fragment) {
float extra_start_width = box_model().padding.left; float extra_start_width = box_model().padding.left;

View file

@ -36,8 +36,8 @@ void NestedBrowsingContextPaintable::paint(PaintContext& context, PaintPhase pha
PaintableBox::paint(context, phase); PaintableBox::paint(context, phase);
if (phase == PaintPhase::Foreground) { if (phase == PaintPhase::Foreground) {
auto clip_rect = absolute_rect().to_rounded<int>(); auto clip_rect = context.rounded_device_rect(absolute_rect().to_type<CSSPixels>());
ScopedCornerRadiusClip corner_clip { context.painter(), clip_rect, normalized_border_radii_data(ShrinkRadiiForBorders::Yes) }; ScopedCornerRadiusClip corner_clip { context, context.painter(), clip_rect, normalized_border_radii_data(ShrinkRadiiForBorders::Yes) };
auto* hosted_document = layout_box().dom_node().content_document_without_origin_check(); auto* hosted_document = layout_box().dom_node().content_document_without_origin_check();
if (!hosted_document) if (!hosted_document)
@ -49,7 +49,7 @@ void NestedBrowsingContextPaintable::paint(PaintContext& context, PaintPhase pha
context.painter().save(); context.painter().save();
auto old_viewport_rect = context.device_viewport_rect(); auto old_viewport_rect = context.device_viewport_rect();
context.painter().add_clip_rect(clip_rect); context.painter().add_clip_rect(clip_rect.to_type<int>());
context.painter().translate(absolute_x(), absolute_y()); context.painter().translate(absolute_x(), absolute_y());
context.set_device_viewport_rect({ {}, layout_box().dom_node().nested_browsing_context()->size() }); context.set_device_viewport_rect({ {}, layout_box().dom_node().nested_browsing_context()->size() });

View file

@ -227,7 +227,7 @@ void PaintableBox::paint_border(PaintContext& context) const
.bottom = computed_values().border_bottom(), .bottom = computed_values().border_bottom(),
.left = computed_values().border_left(), .left = computed_values().border_left(),
}; };
paint_all_borders(context, absolute_border_box_rect(), normalized_border_radii_data(), borders_data); paint_all_borders(context, absolute_border_box_rect().to_type<CSSPixels>(), normalized_border_radii_data(), borders_data);
} }
void PaintableBox::paint_backdrop_filter(PaintContext& context) const void PaintableBox::paint_backdrop_filter(PaintContext& context) const
@ -300,7 +300,8 @@ void PaintableBox::paint_box_shadow(PaintContext& context) const
BorderRadiiData PaintableBox::normalized_border_radii_data(ShrinkRadiiForBorders shrink) const BorderRadiiData PaintableBox::normalized_border_radii_data(ShrinkRadiiForBorders shrink) const
{ {
auto border_radius_data = Painting::normalized_border_radii_data(layout_box(), absolute_border_box_rect(), auto border_radius_data = Painting::normalized_border_radii_data(layout_box(),
absolute_border_box_rect().to_type<CSSPixels>(),
computed_values().border_top_left_radius(), computed_values().border_top_left_radius(),
computed_values().border_top_right_radius(), computed_values().border_top_right_radius(),
computed_values().border_bottom_right_radius(), computed_values().border_bottom_right_radius(),
@ -356,7 +357,7 @@ void PaintableBox::before_children_paint(PaintContext& context, PaintPhase phase
if (overflow_y == CSS::Overflow::Hidden || overflow_x == CSS::Overflow::Hidden) { if (overflow_y == CSS::Overflow::Hidden || overflow_x == CSS::Overflow::Hidden) {
auto border_radii_data = normalized_border_radii_data(ShrinkRadiiForBorders::Yes); auto border_radii_data = normalized_border_radii_data(ShrinkRadiiForBorders::Yes);
if (border_radii_data.has_any_radius()) { if (border_radii_data.has_any_radius()) {
auto corner_clipper = BorderRadiusCornerClipper::create(absolute_padding_box_rect().to_rounded<int>(), border_radii_data, CornerClip::Outside, BorderRadiusCornerClipper::UseCachedBitmap::No); auto corner_clipper = BorderRadiusCornerClipper::create(context, absolute_padding_box_rect().to_type<DevicePixels>(), border_radii_data, CornerClip::Outside, BorderRadiusCornerClipper::UseCachedBitmap::No);
if (corner_clipper.is_error()) { if (corner_clipper.is_error()) {
dbgln("Failed to create overflow border-radius corner clipper: {}", corner_clipper.error()); dbgln("Failed to create overflow border-radius corner clipper: {}", corner_clipper.error());
return; return;
@ -553,7 +554,7 @@ void PaintableWithLines::paint(PaintContext& context, PaintPhase phase) const
auto border_radii = normalized_border_radii_data(ShrinkRadiiForBorders::Yes); auto border_radii = normalized_border_radii_data(ShrinkRadiiForBorders::Yes);
if (border_radii.has_any_radius()) { if (border_radii.has_any_radius()) {
auto clipper = BorderRadiusCornerClipper::create(clip_box, border_radii); auto clipper = BorderRadiusCornerClipper::create(context, clip_box.to_type<DevicePixels>(), border_radii);
if (!clipper.is_error()) { if (!clipper.is_error()) {
corner_clipper = clipper.release_value(); corner_clipper = clipper.release_value();
corner_clipper->sample_under_corners(context.painter()); corner_clipper->sample_under_corners(context.painter());

View file

@ -25,12 +25,12 @@ void paint_box_shadow(PaintContext& context, Gfx::IntRect const& content_rect, B
auto& painter = context.painter(); auto& painter = context.painter();
auto top_left_corner = border_radii.top_left.as_corner(); auto top_left_corner = border_radii.top_left.as_corner(context);
auto top_right_corner = border_radii.top_right.as_corner(); auto top_right_corner = border_radii.top_right.as_corner(context);
auto bottom_right_corner = border_radii.bottom_right.as_corner(); auto bottom_right_corner = border_radii.bottom_right.as_corner(context);
auto bottom_left_corner = border_radii.bottom_left.as_corner(); auto bottom_left_corner = border_radii.bottom_left.as_corner(context);
ScopedCornerRadiusClip corner_clipper { painter, content_rect, border_radii, CornerClip::Inside }; ScopedCornerRadiusClip corner_clipper { context, painter, content_rect.to_type<DevicePixels>(), border_radii, CornerClip::Inside };
// Note: Box-shadow layers are ordered front-to-back, so we paint them in reverse // Note: Box-shadow layers are ordered front-to-back, so we paint them in reverse
for (auto& box_shadow_data : box_shadow_layers.in_reverse()) { for (auto& box_shadow_data : box_shadow_layers.in_reverse()) {