mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 01:07:36 +00:00
LibGfx+Everywhere: Change Gfx::Rect
to be endpoint exclusive
Previously, calling `.right()` on a `Gfx::Rect` would return the last column's coordinate still inside the rectangle, or `left + width - 1`. This is called 'endpoint inclusive' and does not make a lot of sense for `Gfx::Rect<float>` where a rectangle of width 5 at position (0, 0) would return 4 as its right side. This same problem exists for `.bottom()`. This changes `Gfx::Rect` to be endpoint exclusive, which gives us the nice property that `width = right - left` and `height = bottom - top`. It enables us to treat `Gfx::Rect<int>` and `Gfx::Rect<float>` exactly the same. All users of `Gfx::Rect` have been updated accordingly.
This commit is contained in:
parent
b7f4363791
commit
f391ccfe53
88 changed files with 524 additions and 518 deletions
|
@ -309,11 +309,11 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet
|
|||
|
||||
image.resolve_for_size(layout_node, image_rect.size());
|
||||
|
||||
while (image_y <= css_clip_rect.bottom()) {
|
||||
while (image_y < css_clip_rect.bottom()) {
|
||||
image_rect.set_y(image_y);
|
||||
|
||||
auto image_x = initial_image_x;
|
||||
while (image_x <= css_clip_rect.right()) {
|
||||
while (image_x < css_clip_rect.right()) {
|
||||
image_rect.set_x(image_x);
|
||||
auto image_device_rect = context.rounded_device_rect(image_rect);
|
||||
if (image_device_rect != last_image_device_rect && image_device_rect.intersects(context.device_viewport_rect()))
|
||||
|
|
|
@ -85,13 +85,13 @@ void paint_border(PaintContext& context, BorderEdge edge, DevicePixelRect const&
|
|||
auto points_for_edge = [](BorderEdge edge, DevicePixelRect const& rect) -> Points {
|
||||
switch (edge) {
|
||||
case BorderEdge::Top:
|
||||
return { rect.top_left(), rect.top_right() };
|
||||
return { rect.top_left(), rect.top_right().moved_left(1) };
|
||||
case BorderEdge::Right:
|
||||
return { rect.top_right(), rect.bottom_right() };
|
||||
return { rect.top_right().moved_left(1), rect.bottom_right().translated(-1) };
|
||||
case BorderEdge::Bottom:
|
||||
return { rect.bottom_left(), rect.bottom_right() };
|
||||
return { rect.bottom_left().moved_up(1), rect.bottom_right().translated(-1) };
|
||||
default: // Edge::Left
|
||||
return { rect.top_left(), rect.bottom_left() };
|
||||
return { rect.top_left(), rect.bottom_left().moved_up(1) };
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -365,13 +365,13 @@ void paint_all_borders(PaintContext& context, CSSPixelRect const& bordered_rect,
|
|||
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)
|
||||
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));
|
||||
blit_corner(border_rect.top_right().to_type<int>().translated(-top_right.horizontal_radius, 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)
|
||||
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));
|
||||
blit_corner(border_rect.bottom_right().to_type<int>().translated(-bottom_right.horizontal_radius, -bottom_right.vertical_radius), 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)
|
||||
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));
|
||||
blit_corner(border_rect.bottom_left().to_type<int>().translated(0, -bottom_left.vertical_radius), bottom_left.as_rect().translated(0, corner_mask_rect.height().value() - bottom_left.vertical_radius), pick_corner_color(borders_data.bottom, borders_data.left));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ ErrorOr<BorderRadiusCornerClipper> BorderRadiusCornerClipper::create(PaintContex
|
|||
.top_right = top_right,
|
||||
.bottom_right = bottom_right,
|
||||
.bottom_left = bottom_left },
|
||||
.page_locations = { .top_left = border_rect.top_left(), .top_right = border_rect.top_right().translated(-top_right.horizontal_radius + 1, 0), .bottom_right = border_rect.bottom_right().translated(-bottom_right.horizontal_radius + 1, -bottom_right.vertical_radius + 1), .bottom_left = border_rect.bottom_left().translated(0, -bottom_left.vertical_radius + 1) },
|
||||
.page_locations = { .top_left = border_rect.top_left(), .top_right = border_rect.top_right().translated(-top_right.horizontal_radius, 0), .bottom_right = border_rect.bottom_right().translated(-bottom_right.horizontal_radius, -bottom_right.vertical_radius), .bottom_left = border_rect.bottom_left().translated(0, -bottom_left.vertical_radius) },
|
||||
.bitmap_locations = { .top_left = { 0, 0 }, .top_right = { corners_bitmap_size.width() - top_right.horizontal_radius, 0 }, .bottom_right = { corners_bitmap_size.width() - bottom_right.horizontal_radius, corners_bitmap_size.height() - bottom_right.vertical_radius }, .bottom_left = { 0, corners_bitmap_size.height() - bottom_left.vertical_radius } },
|
||||
.corner_bitmap_size = corners_bitmap_size
|
||||
};
|
||||
|
|
|
@ -450,16 +450,16 @@ static void paint_text_decoration(PaintContext& context, Gfx::Painter& painter,
|
|||
return;
|
||||
case CSS::TextDecorationLine::Underline:
|
||||
line_start_point = context.rounded_device_point(fragment_box.top_left().translated(0, baseline + 2));
|
||||
line_end_point = context.rounded_device_point(fragment_box.top_right().translated(0, baseline + 2));
|
||||
line_end_point = context.rounded_device_point(fragment_box.top_right().translated(-1, baseline + 2));
|
||||
break;
|
||||
case CSS::TextDecorationLine::Overline:
|
||||
line_start_point = context.rounded_device_point(fragment_box.top_left().translated(0, baseline - glyph_height));
|
||||
line_end_point = context.rounded_device_point(fragment_box.top_right().translated(0, baseline - glyph_height));
|
||||
line_end_point = context.rounded_device_point(fragment_box.top_right().translated(-1, baseline - glyph_height));
|
||||
break;
|
||||
case CSS::TextDecorationLine::LineThrough: {
|
||||
auto x_height = font.x_height();
|
||||
line_start_point = context.rounded_device_point(fragment_box.top_left().translated(0, baseline - x_height * 0.5f));
|
||||
line_end_point = context.rounded_device_point(fragment_box.top_right().translated(0, baseline - x_height * 0.5f));
|
||||
line_end_point = context.rounded_device_point(fragment_box.top_right().translated(-1, baseline - x_height * 0.5f));
|
||||
break;
|
||||
}
|
||||
case CSS::TextDecorationLine::Blink:
|
||||
|
@ -603,7 +603,7 @@ void PaintableWithLines::paint(PaintContext& context, PaintPhase phase) const
|
|||
context.painter().draw_rect(context.enclosing_device_rect(fragment_absolute_rect).to_type<int>(), Color::Green);
|
||||
context.painter().draw_line(
|
||||
context.rounded_device_point(fragment_absolute_rect.top_left().translated(0, fragment.baseline())).to_type<int>(),
|
||||
context.rounded_device_point(fragment_absolute_rect.top_right().translated(0, fragment.baseline())).to_type<int>(), Color::Red);
|
||||
context.rounded_device_point(fragment_absolute_rect.top_right().translated(-1, fragment.baseline())).to_type<int>(), Color::Red);
|
||||
}
|
||||
if (is<Layout::TextNode>(fragment.layout_node()))
|
||||
paint_text_fragment(context, static_cast<Layout::TextNode const&>(fragment.layout_node()), fragment, phase);
|
||||
|
@ -715,7 +715,7 @@ Optional<HitTestResult> PaintableWithLines::hit_test(CSSPixelPoint position, Hit
|
|||
// The best candidate is either the end of the line above, the beginning of the line below, or the beginning or end of the current line.
|
||||
// We arbitrarily choose to consider the end of the line above and ignore the beginning of the line below.
|
||||
// If we knew the direction of selection, we could make a better choice.
|
||||
if (fragment_absolute_rect.bottom() <= position.y()) { // fully below the fragment
|
||||
if (fragment_absolute_rect.bottom() - 1 <= position.y()) { // fully below the fragment
|
||||
last_good_candidate = HitTestResult { const_cast<Paintable&>(*fragment.layout_node().paintable()), fragment.start() + fragment.length() };
|
||||
} else if (fragment_absolute_rect.top() <= position.y()) { // vertically within the fragment
|
||||
if (position.x() < fragment_absolute_rect.left()) { // left of the fragment
|
||||
|
|
|
@ -234,11 +234,10 @@ void paint_box_shadow(PaintContext& context, CSSPixelRect const& content_rect, B
|
|||
auto top_start = inner_bounding_rect.top() - blurred_edge_thickness;
|
||||
auto bottom_start = inner_bounding_rect.top() + inner_bounding_rect.height() + (blurred_edge_thickness - horizontal_edge_width);
|
||||
|
||||
// Note: The +1s in a few of the following translations are due to the -1s Gfx::Rect::right() and Gfx::Rect::bottom().
|
||||
auto top_left_corner_blit_pos = inner_bounding_rect.top_left().translated(-blurred_edge_thickness, -blurred_edge_thickness);
|
||||
auto top_right_corner_blit_pos = inner_bounding_rect.top_right().translated(-top_right_corner_size.width() + 1 + double_radius, -blurred_edge_thickness);
|
||||
auto bottom_left_corner_blit_pos = inner_bounding_rect.bottom_left().translated(-blurred_edge_thickness, -bottom_left_corner_size.height() + 1 + double_radius);
|
||||
auto bottom_right_corner_blit_pos = inner_bounding_rect.bottom_right().translated(-bottom_right_corner_size.width() + 1 + double_radius, -bottom_right_corner_size.height() + 1 + double_radius);
|
||||
auto top_right_corner_blit_pos = inner_bounding_rect.top_right().translated(-top_right_corner_size.width() + double_radius, -blurred_edge_thickness);
|
||||
auto bottom_left_corner_blit_pos = inner_bounding_rect.bottom_left().translated(-blurred_edge_thickness, -bottom_left_corner_size.height() + double_radius);
|
||||
auto bottom_right_corner_blit_pos = inner_bounding_rect.bottom_right().translated(-bottom_right_corner_size.width() + double_radius, -bottom_right_corner_size.height() + double_radius);
|
||||
|
||||
auto paint_shadow = [&](DevicePixelRect clip_rect) {
|
||||
Gfx::PainterStateSaver save { painter };
|
||||
|
@ -253,15 +252,15 @@ void paint_box_shadow(PaintContext& context, CSSPixelRect const& content_rect, B
|
|||
painter.blit(bottom_right_corner_blit_pos.to_type<int>(), shadow_bitmap, bottom_right_corner_rect.to_type<int>());
|
||||
|
||||
// Horizontal edges
|
||||
for (auto x = inner_bounding_rect.left() + (bottom_left_corner_size.width() - double_radius); x <= inner_bounding_rect.right() - (bottom_right_corner_size.width() - double_radius); ++x)
|
||||
for (auto x = inner_bounding_rect.left() + (bottom_left_corner_size.width() - double_radius); x < inner_bounding_rect.right() - (bottom_right_corner_size.width() - double_radius); ++x)
|
||||
painter.blit({ x, bottom_start }, shadow_bitmap, bottom_edge_rect.to_type<int>());
|
||||
for (auto x = inner_bounding_rect.left() + (top_left_corner_size.width() - double_radius); x <= inner_bounding_rect.right() - (top_right_corner_size.width() - double_radius); ++x)
|
||||
for (auto x = inner_bounding_rect.left() + (top_left_corner_size.width() - double_radius); x < inner_bounding_rect.right() - (top_right_corner_size.width() - double_radius); ++x)
|
||||
painter.blit({ x, top_start }, shadow_bitmap, top_edge_rect.to_type<int>());
|
||||
|
||||
// Vertical edges
|
||||
for (auto y = inner_bounding_rect.top() + (top_right_corner_size.height() - double_radius); y <= inner_bounding_rect.bottom() - (bottom_right_corner_size.height() - double_radius); ++y)
|
||||
for (auto y = inner_bounding_rect.top() + (top_right_corner_size.height() - double_radius); y < inner_bounding_rect.bottom() - (bottom_right_corner_size.height() - double_radius); ++y)
|
||||
painter.blit({ right_start, y }, shadow_bitmap, right_edge_rect.to_type<int>());
|
||||
for (auto y = inner_bounding_rect.top() + (top_left_corner_size.height() - double_radius); y <= inner_bounding_rect.bottom() - (bottom_left_corner_size.height() - double_radius); ++y)
|
||||
for (auto y = inner_bounding_rect.top() + (top_left_corner_size.height() - double_radius); y < inner_bounding_rect.bottom() - (bottom_left_corner_size.height() - double_radius); ++y)
|
||||
painter.blit({ left_start, y }, shadow_bitmap, left_edge_rect.to_type<int>());
|
||||
};
|
||||
|
||||
|
@ -300,13 +299,13 @@ void paint_box_shadow(PaintContext& context, CSSPixelRect const& content_rect, B
|
|||
paint_shadow({ 0, 0, really_large_number, device_content_rect.top() });
|
||||
|
||||
// Everything below content_rect, including sides
|
||||
paint_shadow({ 0, device_content_rect.bottom() + 1, really_large_number, really_large_number });
|
||||
paint_shadow({ 0, device_content_rect.bottom(), really_large_number, really_large_number });
|
||||
|
||||
// Everything directly to the left of content_rect
|
||||
paint_shadow({ 0, device_content_rect.top(), device_content_rect.left(), device_content_rect.height() });
|
||||
|
||||
// Everything directly to the right of content_rect
|
||||
paint_shadow({ device_content_rect.right() + 1, device_content_rect.top(), really_large_number, device_content_rect.height() });
|
||||
paint_shadow({ device_content_rect.right(), device_content_rect.top(), really_large_number, device_content_rect.height() });
|
||||
|
||||
if (top_left_corner) {
|
||||
// Inside the top left corner (the part outside the border radius)
|
||||
|
@ -316,19 +315,19 @@ void paint_box_shadow(PaintContext& context, CSSPixelRect const& content_rect, B
|
|||
|
||||
if (top_right_corner) {
|
||||
// Inside the top right corner (the part outside the border radius)
|
||||
auto top_right = top_right_corner.as_rect().to_type<DevicePixels>().translated(device_content_rect.top_right().translated(-top_right_corner.horizontal_radius + 1, 0));
|
||||
auto top_right = top_right_corner.as_rect().to_type<DevicePixels>().translated(device_content_rect.top_right().translated(-top_right_corner.horizontal_radius, 0));
|
||||
paint_shadow(top_right);
|
||||
}
|
||||
|
||||
if (bottom_right_corner) {
|
||||
// Inside the bottom right corner (the part outside the border radius)
|
||||
auto bottom_right = bottom_right_corner.as_rect().to_type<DevicePixels>().translated(device_content_rect.bottom_right().translated(-bottom_right_corner.horizontal_radius + 1, -bottom_right_corner.vertical_radius + 1));
|
||||
auto bottom_right = bottom_right_corner.as_rect().to_type<DevicePixels>().translated(device_content_rect.bottom_right().translated(-bottom_right_corner.horizontal_radius, -bottom_right_corner.vertical_radius));
|
||||
paint_shadow(bottom_right);
|
||||
}
|
||||
|
||||
if (bottom_left_corner) {
|
||||
// Inside the bottom left corner (the part outside the border radius)
|
||||
auto bottom_left = bottom_left_corner.as_rect().to_type<DevicePixels>().translated(device_content_rect.bottom_left().translated(0, -bottom_left_corner.vertical_radius + 1));
|
||||
auto bottom_left = bottom_left_corner.as_rect().to_type<DevicePixels>().translated(device_content_rect.bottom_left().translated(0, -bottom_left_corner.vertical_radius));
|
||||
paint_shadow(bottom_left);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue