mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 12:47:35 +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
|
@ -204,9 +204,9 @@ template<>
|
|||
FloatRect AffineTransform::map(FloatRect const& rect) const
|
||||
{
|
||||
FloatPoint p1 = map(rect.top_left());
|
||||
FloatPoint p2 = map(rect.top_right().translated(1, 0));
|
||||
FloatPoint p3 = map(rect.bottom_right().translated(1, 1));
|
||||
FloatPoint p4 = map(rect.bottom_left().translated(0, 1));
|
||||
FloatPoint p2 = map(rect.top_right());
|
||||
FloatPoint p3 = map(rect.bottom_right());
|
||||
FloatPoint p4 = map(rect.bottom_left());
|
||||
float left = smallest_of(p1.x(), p2.x(), p3.x(), p4.x());
|
||||
float top = smallest_of(p1.y(), p2.y(), p3.y(), p4.y());
|
||||
float right = largest_of(p1.x(), p2.x(), p3.x(), p4.x());
|
||||
|
|
|
@ -683,11 +683,11 @@ void AntiAliasingPainter::fill_rect_with_rounded_corners(IntRect const& a_rect,
|
|||
if (top_left)
|
||||
fill_corner(top_left_corner, bounding_rect.top_left(), top_left);
|
||||
if (top_right)
|
||||
fill_corner(top_right_corner, bounding_rect.top_right(), top_right);
|
||||
fill_corner(top_right_corner, bounding_rect.top_right().moved_left(1), top_right);
|
||||
if (bottom_left)
|
||||
fill_corner(bottom_left_corner, bounding_rect.bottom_left(), bottom_left);
|
||||
fill_corner(bottom_left_corner, bounding_rect.bottom_left().moved_up(1), bottom_left);
|
||||
if (bottom_right)
|
||||
fill_corner(bottom_right_corner, bounding_rect.bottom_right(), bottom_right);
|
||||
fill_corner(bottom_right_corner, bounding_rect.bottom_right().translated(-1), bottom_right);
|
||||
}
|
||||
|
||||
void AntiAliasingPainter::stroke_segment_intersection(FloatPoint current_line_a, FloatPoint current_line_b, FloatLine const& previous_line, Color color, float thickness)
|
||||
|
|
|
@ -280,12 +280,12 @@ void ClassicStylePainter::paint_frame(Painter& painter, IntRect const& rect, Pal
|
|||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
painter.draw_line(rect.top_left(), rect.top_right(), top_left_color);
|
||||
painter.draw_line(rect.bottom_left(), rect.bottom_right(), bottom_right_color);
|
||||
painter.draw_line(rect.top_left(), rect.top_right().moved_left(1), top_left_color);
|
||||
painter.draw_line(rect.bottom_left().moved_up(1), rect.bottom_right().translated(-1), bottom_right_color);
|
||||
|
||||
if ((style != FrameStyle::SunkenPanel && style != FrameStyle::RaisedPanel) || !skip_vertical_lines) {
|
||||
painter.draw_line(rect.top_left().translated(0, 1), rect.bottom_left().translated(0, -1), top_left_color);
|
||||
painter.draw_line(rect.top_right(), rect.bottom_right().translated(0, -1), bottom_right_color);
|
||||
painter.draw_line(rect.top_left().moved_down(1), rect.bottom_left().moved_up(2), top_left_color);
|
||||
painter.draw_line(rect.top_right().moved_left(1), rect.bottom_right().translated(-1, -2), bottom_right_color);
|
||||
}
|
||||
|
||||
if (style == FrameStyle::RaisedContainer || style == FrameStyle::SunkenContainer) {
|
||||
|
@ -302,19 +302,19 @@ void ClassicStylePainter::paint_frame(Painter& painter, IntRect const& rect, Pal
|
|||
bottom_right_color = light_shade;
|
||||
}
|
||||
IntRect inner_container_frame_rect = rect.shrunken(2, 2);
|
||||
painter.draw_line(inner_container_frame_rect.top_left(), inner_container_frame_rect.top_right(), top_left_color);
|
||||
painter.draw_line(inner_container_frame_rect.bottom_left(), inner_container_frame_rect.bottom_right(), bottom_right_color);
|
||||
painter.draw_line(inner_container_frame_rect.top_left().translated(0, 1), inner_container_frame_rect.bottom_left().translated(0, -1), top_left_color);
|
||||
painter.draw_line(inner_container_frame_rect.top_right(), inner_container_frame_rect.bottom_right().translated(0, -1), bottom_right_color);
|
||||
painter.draw_line(inner_container_frame_rect.top_left(), inner_container_frame_rect.top_right().moved_left(1), top_left_color);
|
||||
painter.draw_line(inner_container_frame_rect.bottom_left().moved_up(1), inner_container_frame_rect.bottom_right().translated(-1), bottom_right_color);
|
||||
painter.draw_line(inner_container_frame_rect.top_left().moved_down(1), inner_container_frame_rect.bottom_left().moved_up(2), top_left_color);
|
||||
painter.draw_line(inner_container_frame_rect.top_right().moved_left(1), inner_container_frame_rect.bottom_right().translated(-1, -2), bottom_right_color);
|
||||
}
|
||||
|
||||
if (style == FrameStyle::RaisedBox || style == FrameStyle::SunkenBox) {
|
||||
swap(top_left_color, bottom_right_color);
|
||||
IntRect inner_rect = rect.shrunken(2, 2);
|
||||
painter.draw_line(inner_rect.top_left(), inner_rect.top_right(), top_left_color);
|
||||
painter.draw_line(inner_rect.bottom_left(), inner_rect.bottom_right(), bottom_right_color);
|
||||
painter.draw_line(inner_rect.top_left().translated(0, 1), inner_rect.bottom_left().translated(0, -1), top_left_color);
|
||||
painter.draw_line(inner_rect.top_right(), inner_rect.bottom_right().translated(0, -1), bottom_right_color);
|
||||
painter.draw_line(inner_rect.top_left(), inner_rect.top_right().moved_left(1), top_left_color);
|
||||
painter.draw_line(inner_rect.bottom_left().moved_up(1), inner_rect.bottom_right().translated(-1), bottom_right_color);
|
||||
painter.draw_line(inner_rect.top_left().moved_down(1), inner_rect.bottom_left().moved_up(2), top_left_color);
|
||||
painter.draw_line(inner_rect.top_right().moved_left(1), inner_rect.bottom_right().translated(-1, -2), bottom_right_color);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -342,22 +342,22 @@ void ClassicStylePainter::paint_window_frame(Painter& painter, IntRect const& re
|
|||
rect.height() - border_thickness },
|
||||
base_color, border_thickness);
|
||||
|
||||
painter.draw_line(rect.top_left().translated(0, 1), rect.bottom_left(), base_color);
|
||||
painter.draw_line(rect.top_left().translated(1, 1), rect.top_right().translated(-1, 1), light_shade);
|
||||
painter.draw_line(rect.top_left().translated(1, 1), rect.bottom_left().translated(1, -1), light_shade);
|
||||
painter.draw_line(rect.top_left().translated(2, 2), rect.top_right().translated(-2, 2), base_color);
|
||||
painter.draw_line(rect.top_left().translated(2, 2), rect.bottom_left().translated(2, -2), base_color);
|
||||
painter.draw_line(rect.top_left().translated(3, 3), rect.top_right().translated(-3, 3), base_color);
|
||||
painter.draw_line(rect.top_left().translated(3, 3), rect.bottom_left().translated(3, -3), base_color);
|
||||
painter.draw_line(rect.top_left().translated(0, 1), rect.bottom_left().translated(0, -1), base_color);
|
||||
painter.draw_line(rect.top_left().translated(1, 1), rect.top_right().translated(-2, 1), light_shade);
|
||||
painter.draw_line(rect.top_left().translated(1, 1), rect.bottom_left().translated(1, -2), light_shade);
|
||||
painter.draw_line(rect.top_left().translated(2, 2), rect.top_right().translated(-3, 2), base_color);
|
||||
painter.draw_line(rect.top_left().translated(2, 2), rect.bottom_left().translated(2, -3), base_color);
|
||||
painter.draw_line(rect.top_left().translated(3, 3), rect.top_right().translated(-4, 3), base_color);
|
||||
painter.draw_line(rect.top_left().translated(3, 3), rect.bottom_left().translated(3, -4), base_color);
|
||||
|
||||
painter.draw_line(rect.top_right(), rect.bottom_right(), dark_shade);
|
||||
painter.draw_line(rect.top_right().translated(-1, 1), rect.bottom_right().translated(-1, -1), mid_shade);
|
||||
painter.draw_line(rect.top_right().translated(-2, 2), rect.bottom_right().translated(-2, -2), base_color);
|
||||
painter.draw_line(rect.top_right().translated(-3, 3), rect.bottom_right().translated(-3, -3), base_color);
|
||||
painter.draw_line(rect.bottom_left(), rect.bottom_right(), dark_shade);
|
||||
painter.draw_line(rect.bottom_left().translated(1, -1), rect.bottom_right().translated(-1, -1), mid_shade);
|
||||
painter.draw_line(rect.bottom_left().translated(2, -2), rect.bottom_right().translated(-2, -2), base_color);
|
||||
painter.draw_line(rect.bottom_left().translated(3, -3), rect.bottom_right().translated(-3, -3), base_color);
|
||||
painter.draw_line(rect.top_right().translated(-1, 0), rect.bottom_right().translated(-1, -1), dark_shade);
|
||||
painter.draw_line(rect.top_right().translated(-2, 1), rect.bottom_right().translated(-2, -2), mid_shade);
|
||||
painter.draw_line(rect.top_right().translated(-3, 2), rect.bottom_right().translated(-3, -3), base_color);
|
||||
painter.draw_line(rect.top_right().translated(-4, 3), rect.bottom_right().translated(-4, -4), base_color);
|
||||
painter.draw_line(rect.bottom_left().translated(0, -1), rect.bottom_right().translated(-1, -1), dark_shade);
|
||||
painter.draw_line(rect.bottom_left().translated(1, -2), rect.bottom_right().translated(-2, -2), mid_shade);
|
||||
painter.draw_line(rect.bottom_left().translated(2, -3), rect.bottom_right().translated(-3, -3), base_color);
|
||||
painter.draw_line(rect.bottom_left().translated(3, -4), rect.bottom_right().translated(-4, -4), base_color);
|
||||
}
|
||||
|
||||
void ClassicStylePainter::paint_progressbar(Painter& painter, IntRect const& rect, Palette const& palette, int min, int max, int value, StringView text, Orientation orientation)
|
||||
|
@ -624,7 +624,7 @@ void ClassicStylePainter::paint_simple_rect_shadow(Painter& painter, IntRect con
|
|||
auto half_width = containing_horizontal_rect.width() / 2;
|
||||
int corner_piece_width = min(containing_horizontal_rect.width() / 2, base_size * 2);
|
||||
int left_corners_right = containing_horizontal_rect.left() + corner_piece_width;
|
||||
int right_corners_left = max(containing_horizontal_rect.right() - corner_piece_width + 1, left_corners_right + 1);
|
||||
int right_corners_left = max(containing_horizontal_rect.right() - corner_piece_width, left_corners_right + 1);
|
||||
auto paint_horizontal = [&](int y, int src_row) {
|
||||
if (half_width <= 0)
|
||||
return;
|
||||
|
@ -639,7 +639,7 @@ void ClassicStylePainter::paint_simple_rect_shadow(Painter& painter, IntRect con
|
|||
};
|
||||
|
||||
paint_horizontal(containing_rect.top(), 0);
|
||||
paint_horizontal(containing_rect.bottom() - base_size + 1, 1);
|
||||
paint_horizontal(containing_rect.bottom() - base_size, 1);
|
||||
|
||||
int corner_piece_height = min(half_height, base_size);
|
||||
int top_corners_bottom = base_size + corner_piece_height;
|
||||
|
@ -658,7 +658,7 @@ void ClassicStylePainter::paint_simple_rect_shadow(Painter& painter, IntRect con
|
|||
paint_vertical(containing_rect.left(), 0, horizontal_shift, 0);
|
||||
if (shadow_includes_frame)
|
||||
horizontal_shift = 0; // TODO: fix off-by-one on rectangles barely wide enough
|
||||
paint_vertical(containing_rect.right() - base_size + 1, 1, 0, horizontal_shift);
|
||||
paint_vertical(containing_rect.right() - base_size, 1, 0, horizontal_shift);
|
||||
|
||||
if (fill_content) {
|
||||
// Fill the enclosed rectangle with the RGBA color of the right-bottom pixel of the TL tile
|
||||
|
|
|
@ -64,8 +64,8 @@ void ClassicWindowTheme::paint_normal_frame(Painter& painter, WindowState window
|
|||
|
||||
auto [title_color, border_color, border_color2, stripes_color, shadow_color] = compute_frame_colors(window_state, palette);
|
||||
|
||||
painter.draw_line(titlebar_rect.bottom_left().translated(0, 1), titlebar_rect.bottom_right().translated(0, 1), palette.button());
|
||||
painter.draw_line(titlebar_rect.bottom_left().translated(0, 2), titlebar_rect.bottom_right().translated(0, 2), palette.button());
|
||||
painter.draw_line(titlebar_rect.bottom_left(), titlebar_rect.bottom_right().moved_left(1), palette.button());
|
||||
painter.draw_line(titlebar_rect.bottom_left().moved_down(1), titlebar_rect.bottom_right().translated(-1, 1), palette.button());
|
||||
|
||||
painter.fill_rect_with_gradient(titlebar_rect, border_color, border_color2);
|
||||
|
||||
|
@ -87,7 +87,7 @@ void ClassicWindowTheme::paint_normal_frame(Painter& painter, WindowState window
|
|||
if (stripes_color.alpha() > 0) {
|
||||
switch (title_alignment) {
|
||||
case Gfx::TextAlignment::CenterLeft: {
|
||||
int stripe_left = titlebar_title_rect.right() + 5;
|
||||
int stripe_left = titlebar_title_rect.right() + 4;
|
||||
|
||||
if (stripe_left && stripe_right && stripe_left < stripe_right) {
|
||||
for (int i = 2; i <= titlebar_inner_rect.height() - 2; i += 2) {
|
||||
|
@ -164,12 +164,11 @@ void ClassicWindowTheme::paint_notification_frame(Painter& painter, WindowMode w
|
|||
painter.fill_rect_with_gradient(Gfx::Orientation::Vertical, titlebar_rect, palette.active_window_border1(), palette.active_window_border2());
|
||||
|
||||
if (palette.active_window_title_stripes().alpha() > 0) {
|
||||
int stripe_top = close_button_rect.bottom() + 4;
|
||||
int stripe_top = close_button_rect.bottom() + 3;
|
||||
int stripe_bottom = window_rect.height() - 3;
|
||||
if (stripe_top && stripe_bottom && stripe_top < stripe_bottom) {
|
||||
for (int i = 2; i <= palette.window_title_height() - 2; i += 2) {
|
||||
for (int i = 2; i <= palette.window_title_height() - 2; i += 2)
|
||||
painter.draw_line({ titlebar_rect.x() + i, stripe_top }, { titlebar_rect.x() + i, stripe_bottom }, palette.active_window_title_stripes());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -208,7 +207,7 @@ Vector<IntRect> ClassicWindowTheme::layout_buttons(WindowType window_type, Windo
|
|||
if (window_type == WindowType::Notification)
|
||||
pos = titlebar_rect(window_type, window_mode, window_rect, palette).top() + 2;
|
||||
else
|
||||
pos = titlebar_text_rect(window_type, window_mode, window_rect, palette).right() + 1;
|
||||
pos = titlebar_text_rect(window_type, window_mode, window_rect, palette).right();
|
||||
|
||||
for (size_t i = 0; i < buttons; i++) {
|
||||
if (window_type == WindowType::Notification) {
|
||||
|
|
|
@ -68,7 +68,7 @@ ALWAYS_INLINE void Painter::draw_scanline_for_fill_path(int y, T x_start, T x_en
|
|||
if (paint_left_subpixel)
|
||||
set_physical_pixel(clipped.top_left(), get_color_with_alpha(0, left_subpixel_alpha), true);
|
||||
if (paint_right_subpixel)
|
||||
set_physical_pixel(clipped.top_right(), get_color_with_alpha(scanline.width(), right_subpixel_alpha), true);
|
||||
set_physical_pixel(clipped.top_right().moved_left(1), get_color_with_alpha(scanline.width(), right_subpixel_alpha), true);
|
||||
clipped.shrink(0, paint_right_subpixel, 0, paint_left_subpixel);
|
||||
if (clipped.is_empty())
|
||||
return;
|
||||
|
@ -82,9 +82,8 @@ ALWAYS_INLINE void Painter::draw_scanline_for_fill_path(int y, T x_start, T x_en
|
|||
}
|
||||
}
|
||||
|
||||
for (int x = clipped.x(); x <= clipped.right(); x++) {
|
||||
for (int x = clipped.x(); x < clipped.right(); x++)
|
||||
set_physical_pixel({ x, clipped.y() }, get_color(x - scanline.x()), true);
|
||||
}
|
||||
}
|
||||
|
||||
[[maybe_unused]] inline void approximately_place_on_int_grid(FloatPoint ffrom, FloatPoint fto, IntPoint& from, IntPoint& to, Optional<IntPoint> previous_to)
|
||||
|
@ -144,8 +143,8 @@ void Painter::fill_path_impl(Path const& path, ColorOrFunction color, Gfx::Paint
|
|||
active_list.ensure_capacity(segments.size());
|
||||
|
||||
// first, grab the segments for the very first scanline
|
||||
GridCoordinateType first_y = path.bounding_box().bottom_right().y() + 1;
|
||||
GridCoordinateType last_y = path.bounding_box().top_left().y() - 1;
|
||||
GridCoordinateType first_y = path.bounding_box().bottom();
|
||||
GridCoordinateType last_y = path.bounding_box().top() - 1;
|
||||
float scanline = first_y;
|
||||
|
||||
size_t last_active_segment { 0 };
|
||||
|
|
|
@ -110,7 +110,7 @@ public:
|
|||
FloatVector3 value(0, 0, 0);
|
||||
for (auto k = 0l; k < (ssize_t)N; ++k) {
|
||||
auto ki = i + k - offset;
|
||||
if (ki < source_rect.x() || ki > source_rect.right()) {
|
||||
if (ki < source_rect.x() || ki >= source_rect.right()) {
|
||||
if (parameters.should_wrap())
|
||||
ki = (ki + source.size().width()) % source.size().width(); // TODO: fix up using source_rect
|
||||
else
|
||||
|
@ -119,7 +119,7 @@ public:
|
|||
|
||||
for (auto l = 0l; l < (ssize_t)N; ++l) {
|
||||
auto lj = j + l - offset;
|
||||
if (lj < source_rect.y() || lj > source_rect.bottom()) {
|
||||
if (lj < source_rect.y() || lj >= source_rect.bottom()) {
|
||||
if (parameters.should_wrap())
|
||||
lj = (lj + source.size().height()) % source.size().height(); // TODO: fix up using source_rect
|
||||
else
|
||||
|
|
|
@ -560,18 +560,14 @@ static void for_each_pixel_around_rect_clockwise(RectType const& rect, Callback
|
|||
{
|
||||
if (rect.is_empty())
|
||||
return;
|
||||
for (auto x = rect.left(); x <= rect.right(); ++x) {
|
||||
for (auto x = rect.left(); x < rect.right(); ++x)
|
||||
callback(x, rect.top());
|
||||
}
|
||||
for (auto y = rect.top() + 1; y <= rect.bottom(); ++y) {
|
||||
callback(rect.right(), y);
|
||||
}
|
||||
for (auto x = rect.right() - 1; x >= rect.left(); --x) {
|
||||
callback(x, rect.bottom());
|
||||
}
|
||||
for (auto y = rect.bottom() - 1; y > rect.top(); --y) {
|
||||
for (auto y = rect.top() + 1; y < rect.bottom(); ++y)
|
||||
callback(rect.right() - 1, y);
|
||||
for (auto x = rect.right() - 2; x >= rect.left(); --x)
|
||||
callback(x, rect.bottom() - 1);
|
||||
for (auto y = rect.bottom() - 2; y > rect.top(); --y)
|
||||
callback(rect.left(), y);
|
||||
}
|
||||
}
|
||||
|
||||
void Painter::draw_focus_rect(IntRect const& rect, Color color)
|
||||
|
@ -596,17 +592,17 @@ void Painter::draw_rect(IntRect const& a_rect, Color color, bool rough)
|
|||
return;
|
||||
|
||||
int min_y = clipped_rect.top();
|
||||
int max_y = clipped_rect.bottom();
|
||||
int max_y = clipped_rect.bottom() - 1;
|
||||
int scale = this->scale();
|
||||
|
||||
if (rect.top() >= clipped_rect.top() && rect.top() <= clipped_rect.bottom()) {
|
||||
if (rect.top() >= clipped_rect.top() && rect.top() < clipped_rect.bottom()) {
|
||||
int start_x = rough ? max(rect.x() + 1, clipped_rect.x()) : clipped_rect.x();
|
||||
int width = rough ? min(rect.width() - 2, clipped_rect.width()) : clipped_rect.width();
|
||||
for (int i = 0; i < scale; ++i)
|
||||
fill_physical_scanline_with_draw_op(rect.top() * scale + i, start_x * scale, width * scale, color);
|
||||
++min_y;
|
||||
}
|
||||
if (rect.bottom() >= clipped_rect.top() && rect.bottom() <= clipped_rect.bottom()) {
|
||||
if (rect.bottom() > clipped_rect.top() && rect.bottom() <= clipped_rect.bottom()) {
|
||||
int start_x = rough ? max(rect.x() + 1, clipped_rect.x()) : clipped_rect.x();
|
||||
int width = rough ? min(rect.width() - 2, clipped_rect.width()) : clipped_rect.width();
|
||||
for (int i = 0; i < scale; ++i)
|
||||
|
@ -624,7 +620,7 @@ void Painter::draw_rect(IntRect const& a_rect, Color color, bool rough)
|
|||
for (int i = 0; i < scale; ++i)
|
||||
set_physical_pixel_with_draw_op(bits[rect.left() * scale + i], color);
|
||||
for (int i = 0; i < scale; ++i)
|
||||
set_physical_pixel_with_draw_op(bits[rect.right() * scale + i], color);
|
||||
set_physical_pixel_with_draw_op(bits[(rect.right() - 1) * scale + i], color);
|
||||
}
|
||||
} else {
|
||||
for (int y = min_y * scale; y <= max_y * scale; ++y) {
|
||||
|
@ -634,7 +630,7 @@ void Painter::draw_rect(IntRect const& a_rect, Color color, bool rough)
|
|||
set_physical_pixel_with_draw_op(bits[rect.left() * scale + i], color);
|
||||
if (draw_right_side)
|
||||
for (int i = 0; i < scale; ++i)
|
||||
set_physical_pixel_with_draw_op(bits[rect.right() * scale + i], color);
|
||||
set_physical_pixel_with_draw_op(bits[(rect.right() - 1) * scale + i], color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -672,8 +668,8 @@ void Painter::draw_bitmap(IntPoint p, CharacterBitmap const& bitmap, Color color
|
|||
char const* bitmap_row = &bitmap.bits()[first_row * bitmap.width() + first_column];
|
||||
size_t const bitmap_skip = bitmap.width();
|
||||
|
||||
for (int row = first_row; row <= last_row; ++row) {
|
||||
for (int j = 0; j <= (last_column - first_column); ++j) {
|
||||
for (int row = first_row; row < last_row; ++row) {
|
||||
for (int j = 0; j < (last_column - first_column); ++j) {
|
||||
char fc = bitmap_row[j];
|
||||
if (fc == '#')
|
||||
dst[j] = color.value();
|
||||
|
@ -700,16 +696,16 @@ void Painter::draw_bitmap(IntPoint p, GlyphBitmap const& bitmap, Color color)
|
|||
size_t const dst_skip = m_target->pitch() / sizeof(ARGB32);
|
||||
|
||||
if (scale == 1) {
|
||||
for (int row = first_row; row <= last_row; ++row) {
|
||||
for (int j = 0; j <= (last_column - first_column); ++j) {
|
||||
for (int row = first_row; row < last_row; ++row) {
|
||||
for (int j = 0; j < (last_column - first_column); ++j) {
|
||||
if (bitmap.bit_at(j + first_column, row))
|
||||
dst[j] = color_for_format(dst_format, dst[j]).blend(color).value();
|
||||
}
|
||||
dst += dst_skip;
|
||||
}
|
||||
} else {
|
||||
for (int row = first_row; row <= last_row; ++row) {
|
||||
for (int j = 0; j <= (last_column - first_column); ++j) {
|
||||
for (int row = first_row; row < last_row; ++row) {
|
||||
for (int j = 0; j < (last_column - first_column); ++j) {
|
||||
if (bitmap.bit_at((j + first_column), row)) {
|
||||
for (int iy = 0; iy < scale; ++iy)
|
||||
for (int ix = 0; ix < scale; ++ix) {
|
||||
|
@ -753,7 +749,7 @@ void Painter::draw_triangle(IntPoint a, IntPoint b, IntPoint c, Color color)
|
|||
|
||||
// return if top is below clip rect or bottom is above clip rect
|
||||
auto clip = clip_rect();
|
||||
if (p0.y() >= clip.bottom())
|
||||
if (p0.y() >= clip.bottom() - 1)
|
||||
return;
|
||||
if (p2.y() < clip.top())
|
||||
return;
|
||||
|
@ -801,7 +797,7 @@ void Painter::draw_triangle(IntPoint a, IntPoint b, IntPoint c, Color color)
|
|||
|
||||
int rgba = color.value();
|
||||
|
||||
for (int y = max(p0.y(), clip.top()); y <= min(p2.y(), clip.bottom()); y++) {
|
||||
for (int y = max(p0.y(), clip.top()); y < min(p2.y() + 1, clip.bottom()); y++) {
|
||||
Optional<int>
|
||||
x0 = l0.intersection_on_x(y),
|
||||
x1 = l1.intersection_on_x(y),
|
||||
|
@ -827,9 +823,8 @@ void Painter::draw_triangle(IntPoint a, IntPoint b, IntPoint c, Color color)
|
|||
int left_bound = result_a, right_bound = result_b;
|
||||
|
||||
ARGB32* scanline = m_target->scanline(y);
|
||||
for (int x = max(left_bound, clip.left()); x <= min(right_bound, clip.right()); x++) {
|
||||
for (int x = max(left_bound, clip.left()); x <= min(right_bound, clip.right() - 1); x++)
|
||||
scanline[x] = rgba;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -920,8 +915,8 @@ void Painter::blit_with_opacity(IntPoint position, Gfx::Bitmap const& source, In
|
|||
.dst = m_target->scanline(clipped_rect.y()) + clipped_rect.x(),
|
||||
.src_pitch = source.pitch() / sizeof(ARGB32),
|
||||
.dst_pitch = m_target->pitch() / sizeof(ARGB32),
|
||||
.row_count = last_row - first_row + 1,
|
||||
.column_count = last_column - first_column + 1,
|
||||
.row_count = last_row - first_row,
|
||||
.column_count = last_column - first_column,
|
||||
.opacity = opacity,
|
||||
.src_format = source.format(),
|
||||
};
|
||||
|
@ -968,8 +963,8 @@ void Painter::blit_filtered(IntPoint position, Gfx::Bitmap const& source, IntRec
|
|||
ARGB32 const* src = source.scanline(safe_src_rect.top() + first_row) + safe_src_rect.left() + first_column;
|
||||
size_t const src_skip = source.pitch() / sizeof(ARGB32);
|
||||
|
||||
for (int row = first_row; row <= last_row; ++row) {
|
||||
for (int x = 0; x <= (last_column - first_column); ++x) {
|
||||
for (int row = first_row; row < last_row; ++row) {
|
||||
for (int x = 0; x < (last_column - first_column); ++x) {
|
||||
u8 alpha = color_for_format(src_format, src[x]).alpha();
|
||||
if (alpha == 0xff) {
|
||||
auto color = filter(Color::from_argb(src[x]));
|
||||
|
@ -986,9 +981,9 @@ void Painter::blit_filtered(IntPoint position, Gfx::Bitmap const& source, IntRec
|
|||
src += src_skip;
|
||||
}
|
||||
} else {
|
||||
for (int row = first_row; row <= last_row; ++row) {
|
||||
for (int row = first_row; row < last_row; ++row) {
|
||||
ARGB32 const* src = source.scanline(safe_src_rect.top() + row / s) + safe_src_rect.left() + first_column / s;
|
||||
for (int x = 0; x <= (last_column - first_column); ++x) {
|
||||
for (int x = 0; x < (last_column - first_column); ++x) {
|
||||
u8 alpha = color_for_format(src_format, src[x / s]).alpha();
|
||||
if (alpha == 0xff) {
|
||||
auto color = filter(color_for_format(src_format, src[x / s]));
|
||||
|
@ -1033,9 +1028,9 @@ void Painter::draw_tiled_bitmap(IntRect const& a_dst_rect, Gfx::Bitmap const& so
|
|||
clipped_rect *= scale;
|
||||
dst_rect *= scale;
|
||||
|
||||
int const first_row = (clipped_rect.top() - dst_rect.top());
|
||||
int const last_row = (clipped_rect.bottom() - dst_rect.top());
|
||||
int const first_column = (clipped_rect.left() - dst_rect.left());
|
||||
int const first_row = clipped_rect.top() - dst_rect.top();
|
||||
int const last_row = clipped_rect.bottom() - dst_rect.top();
|
||||
int const first_column = clipped_rect.left() - dst_rect.left();
|
||||
ARGB32* dst = m_target->scanline(clipped_rect.y()) + clipped_rect.x();
|
||||
size_t const dst_skip = m_target->pitch() / sizeof(ARGB32);
|
||||
|
||||
|
@ -1043,20 +1038,18 @@ void Painter::draw_tiled_bitmap(IntRect const& a_dst_rect, Gfx::Bitmap const& so
|
|||
int s = scale / source.scale();
|
||||
if (s == 1) {
|
||||
int x_start = first_column + a_dst_rect.left() * scale;
|
||||
for (int row = first_row; row <= last_row; ++row) {
|
||||
for (int row = first_row; row < last_row; ++row) {
|
||||
ARGB32 const* sl = source.scanline((row + a_dst_rect.top() * scale) % source.physical_height());
|
||||
for (int x = x_start; x < clipped_rect.width() + x_start; ++x) {
|
||||
for (int x = x_start; x < clipped_rect.width() + x_start; ++x)
|
||||
dst[x - x_start] = sl[x % source.physical_width()];
|
||||
}
|
||||
dst += dst_skip;
|
||||
}
|
||||
} else {
|
||||
int x_start = first_column + a_dst_rect.left() * scale;
|
||||
for (int row = first_row; row <= last_row; ++row) {
|
||||
for (int row = first_row; row < last_row; ++row) {
|
||||
ARGB32 const* sl = source.scanline(((row + a_dst_rect.top() * scale) / s) % source.physical_height());
|
||||
for (int x = x_start; x < clipped_rect.width() + x_start; ++x) {
|
||||
for (int x = x_start; x < clipped_rect.width() + x_start; ++x)
|
||||
dst[x - x_start] = sl[(x / s) % source.physical_width()];
|
||||
}
|
||||
dst += dst_skip;
|
||||
}
|
||||
}
|
||||
|
@ -1114,7 +1107,7 @@ void Painter::blit(IntPoint position, Gfx::Bitmap const& source, IntRect const&
|
|||
if (source.format() == BitmapFormat::BGRx8888 || source.format() == BitmapFormat::BGRA8888) {
|
||||
ARGB32 const* src = source.scanline(src_rect.top() + first_row) + src_rect.left() + first_column;
|
||||
size_t const src_skip = source.pitch() / sizeof(ARGB32);
|
||||
for (int row = first_row; row <= last_row; ++row) {
|
||||
for (int row = first_row; row < last_row; ++row) {
|
||||
memcpy(dst, src, sizeof(ARGB32) * clipped_rect.width());
|
||||
dst += dst_skip;
|
||||
src += src_skip;
|
||||
|
@ -1125,7 +1118,7 @@ void Painter::blit(IntPoint position, Gfx::Bitmap const& source, IntRect const&
|
|||
if (source.format() == BitmapFormat::RGBA8888) {
|
||||
u32 const* src = source.scanline(src_rect.top() + first_row) + src_rect.left() + first_column;
|
||||
size_t const src_skip = source.pitch() / sizeof(u32);
|
||||
for (int row = first_row; row <= last_row; ++row) {
|
||||
for (int row = first_row; row < last_row; ++row) {
|
||||
for (int i = 0; i < clipped_rect.width(); ++i) {
|
||||
u32 rgba = src[i];
|
||||
u32 bgra = (rgba & 0xff00ff00)
|
||||
|
@ -1200,9 +1193,9 @@ ALWAYS_INLINE static void do_draw_box_sampled_scaled_bitmap(Gfx::Bitmap& target,
|
|||
return (intersected_right - intersected_left) * (intersected_bottom - intersected_top);
|
||||
};
|
||||
|
||||
for (int y = clipped_rect.top(); y <= clipped_rect.bottom(); ++y) {
|
||||
for (int y = clipped_rect.top(); y < clipped_rect.bottom(); ++y) {
|
||||
auto* scanline = reinterpret_cast<Color*>(target.scanline(y));
|
||||
for (int x = clipped_rect.left(); x <= clipped_rect.right(); ++x) {
|
||||
for (int x = clipped_rect.left(); x < clipped_rect.right(); ++x) {
|
||||
// Project the destination pixel in the source image
|
||||
FloatRect const source_box = {
|
||||
src_rect.left() + (x - dst_rect.x()) * source_pixel_width,
|
||||
|
@ -1217,8 +1210,8 @@ ALWAYS_INLINE static void do_draw_box_sampled_scaled_bitmap(Gfx::Bitmap& target,
|
|||
float green_accumulator = 0.f;
|
||||
float blue_accumulator = 0.f;
|
||||
float total_area = 0.f;
|
||||
for (int sy = enclosing_source_box.y(); sy <= enclosing_source_box.bottom(); ++sy) {
|
||||
for (int sx = enclosing_source_box.x(); sx <= enclosing_source_box.right(); ++sx) {
|
||||
for (int sy = enclosing_source_box.y(); sy < enclosing_source_box.bottom(); ++sy) {
|
||||
for (int sx = enclosing_source_box.x(); sx < enclosing_source_box.right(); ++sx) {
|
||||
float area = float_rect_intersection_area_fixme(source_box, pixel_box.translated(sx, sy));
|
||||
|
||||
auto pixel = get_pixel(source, sx, sy);
|
||||
|
@ -1281,11 +1274,11 @@ ALWAYS_INLINE static void do_draw_scaled_bitmap(Gfx::Bitmap& target, IntRect con
|
|||
i64 src_left = src_rect.left() * shift;
|
||||
i64 src_top = src_rect.top() * shift;
|
||||
|
||||
for (int y = clipped_rect.top(); y <= clipped_rect.bottom(); ++y) {
|
||||
for (int y = clipped_rect.top(); y < clipped_rect.bottom(); ++y) {
|
||||
auto* scanline = reinterpret_cast<Color*>(target.scanline(y));
|
||||
auto desired_y = (y - dst_rect.y()) * vscale + src_top;
|
||||
|
||||
for (int x = clipped_rect.left(); x <= clipped_rect.right(); ++x) {
|
||||
for (int x = clipped_rect.left(); x < clipped_rect.right(); ++x) {
|
||||
auto desired_x = (x - dst_rect.x()) * hscale + src_left;
|
||||
|
||||
Color src_pixel;
|
||||
|
@ -1293,10 +1286,10 @@ ALWAYS_INLINE static void do_draw_scaled_bitmap(Gfx::Bitmap& target, IntRect con
|
|||
auto shifted_x = desired_x + bilinear_offset_x;
|
||||
auto shifted_y = desired_y + bilinear_offset_y;
|
||||
|
||||
auto scaled_x0 = clamp(shifted_x >> 32, clipped_src_rect.left(), clipped_src_rect.right());
|
||||
auto scaled_x1 = clamp((shifted_x >> 32) + 1, clipped_src_rect.left(), clipped_src_rect.right());
|
||||
auto scaled_y0 = clamp(shifted_y >> 32, clipped_src_rect.top(), clipped_src_rect.bottom());
|
||||
auto scaled_y1 = clamp((shifted_y >> 32) + 1, clipped_src_rect.top(), clipped_src_rect.bottom());
|
||||
auto scaled_x0 = clamp(shifted_x >> 32, clipped_src_rect.left(), clipped_src_rect.right() - 1);
|
||||
auto scaled_x1 = clamp((shifted_x >> 32) + 1, clipped_src_rect.left(), clipped_src_rect.right() - 1);
|
||||
auto scaled_y0 = clamp(shifted_y >> 32, clipped_src_rect.top(), clipped_src_rect.bottom() - 1);
|
||||
auto scaled_y1 = clamp((shifted_y >> 32) + 1, clipped_src_rect.top(), clipped_src_rect.bottom() - 1);
|
||||
|
||||
float x_ratio = (shifted_x & fractional_mask) / static_cast<float>(shift);
|
||||
float y_ratio = (shifted_y & fractional_mask) / static_cast<float>(shift);
|
||||
|
@ -1311,10 +1304,10 @@ ALWAYS_INLINE static void do_draw_scaled_bitmap(Gfx::Bitmap& target, IntRect con
|
|||
|
||||
src_pixel = top.mixed_with(bottom, y_ratio);
|
||||
} else if constexpr (scaling_mode == Painter::ScalingMode::SmoothPixels) {
|
||||
auto scaled_x1 = clamp(desired_x >> 32, clipped_src_rect.left(), clipped_src_rect.right());
|
||||
auto scaled_x0 = clamp(scaled_x1 - 1, clipped_src_rect.left(), clipped_src_rect.right());
|
||||
auto scaled_y1 = clamp(desired_y >> 32, clipped_src_rect.top(), clipped_src_rect.bottom());
|
||||
auto scaled_y0 = clamp(scaled_y1 - 1, clipped_src_rect.top(), clipped_src_rect.bottom());
|
||||
auto scaled_x1 = clamp(desired_x >> 32, clipped_src_rect.left(), clipped_src_rect.right() - 1);
|
||||
auto scaled_x0 = clamp(scaled_x1 - 1, clipped_src_rect.left(), clipped_src_rect.right() - 1);
|
||||
auto scaled_y1 = clamp(desired_y >> 32, clipped_src_rect.top(), clipped_src_rect.bottom() - 1);
|
||||
auto scaled_y0 = clamp(scaled_y1 - 1, clipped_src_rect.top(), clipped_src_rect.bottom() - 1);
|
||||
|
||||
float x_ratio = (desired_x & fractional_mask) / (float)shift;
|
||||
float y_ratio = (desired_y & fractional_mask) / (float)shift;
|
||||
|
@ -1332,8 +1325,8 @@ ALWAYS_INLINE static void do_draw_scaled_bitmap(Gfx::Bitmap& target, IntRect con
|
|||
|
||||
src_pixel = top.mixed_with(bottom, scaled_y_ratio);
|
||||
} else {
|
||||
auto scaled_x = clamp(desired_x >> 32, clipped_src_rect.left(), clipped_src_rect.right());
|
||||
auto scaled_y = clamp(desired_y >> 32, clipped_src_rect.top(), clipped_src_rect.bottom());
|
||||
auto scaled_x = clamp(desired_x >> 32, clipped_src_rect.left(), clipped_src_rect.right() - 1);
|
||||
auto scaled_y = clamp(desired_y >> 32, clipped_src_rect.top(), clipped_src_rect.bottom() - 1);
|
||||
src_pixel = get_pixel(source, scaled_x, scaled_y);
|
||||
}
|
||||
|
||||
|
@ -1556,7 +1549,7 @@ void draw_text_line(FloatRect const& a_rect, Utf8View const& text, Font const& f
|
|||
case TextAlignment::TopRight:
|
||||
case TextAlignment::CenterRight:
|
||||
case TextAlignment::BottomRight:
|
||||
rect.set_x(rect.right() - font.width(text));
|
||||
rect.set_x(rect.right() - 1 - font.width(text));
|
||||
break;
|
||||
case TextAlignment::TopCenter:
|
||||
case TextAlignment::BottomCenter:
|
||||
|
@ -2043,16 +2036,16 @@ void Painter::draw_line(IntPoint a_p1, IntPoint a_p2, Color color, int thickness
|
|||
// Special case: vertical line.
|
||||
if (point1.x() == point2.x()) {
|
||||
int const x = point1.x();
|
||||
if (x < clip_rect.left() || x > clip_rect.right())
|
||||
if (x < clip_rect.left() || x >= clip_rect.right())
|
||||
return;
|
||||
if (point1.y() > point2.y())
|
||||
swap(point1, point2);
|
||||
if (point1.y() > clip_rect.bottom())
|
||||
if (point1.y() >= clip_rect.bottom())
|
||||
return;
|
||||
if (point2.y() < clip_rect.top())
|
||||
return;
|
||||
int min_y = max(point1.y(), clip_rect.top());
|
||||
int max_y = min(point2.y(), clip_rect.bottom());
|
||||
int max_y = min(point2.y(), clip_rect.bottom() - 1);
|
||||
if (style == LineStyle::Dotted) {
|
||||
for (int y = min_y; y <= max_y; y += thickness * 2)
|
||||
draw_physical_pixel({ x, y }, color, thickness);
|
||||
|
@ -2078,16 +2071,16 @@ void Painter::draw_line(IntPoint a_p1, IntPoint a_p2, Color color, int thickness
|
|||
// Special case: horizontal line.
|
||||
if (point1.y() == point2.y()) {
|
||||
int const y = point1.y();
|
||||
if (y < clip_rect.top() || y > clip_rect.bottom())
|
||||
if (y < clip_rect.top() || y >= clip_rect.bottom())
|
||||
return;
|
||||
if (point1.x() > point2.x())
|
||||
swap(point1, point2);
|
||||
if (point1.x() > clip_rect.right())
|
||||
if (point1.x() >= clip_rect.right())
|
||||
return;
|
||||
if (point2.x() < clip_rect.left())
|
||||
return;
|
||||
int min_x = max(point1.x(), clip_rect.left());
|
||||
int max_x = min(point2.x(), clip_rect.right());
|
||||
int max_x = min(point2.x(), clip_rect.right() - 1);
|
||||
if (style == LineStyle::Dotted) {
|
||||
for (int x = min_x; x <= max_x; x += thickness * 2)
|
||||
draw_physical_pixel({ x, y }, color, thickness);
|
||||
|
@ -2490,19 +2483,17 @@ void Painter::blit_tiled(IntRect const& dst_rect, Gfx::Bitmap const& bitmap, Int
|
|||
{
|
||||
auto tile_width = rect.width();
|
||||
auto tile_height = rect.height();
|
||||
auto dst_right = dst_rect.right();
|
||||
auto dst_bottom = dst_rect.bottom();
|
||||
auto dst_right = dst_rect.right() - 1;
|
||||
auto dst_bottom = dst_rect.bottom() - 1;
|
||||
for (int tile_y = dst_rect.top(); tile_y < dst_bottom; tile_y += tile_height) {
|
||||
for (int tile_x = dst_rect.left(); tile_x < dst_right; tile_x += tile_width) {
|
||||
IntRect tile_src_rect = rect;
|
||||
auto tile_x_overflow = tile_x + tile_width - dst_right;
|
||||
if (tile_x_overflow > 0) {
|
||||
if (tile_x_overflow > 0)
|
||||
tile_src_rect.set_width(tile_width - tile_x_overflow);
|
||||
}
|
||||
auto tile_y_overflow = tile_y + tile_height - dst_bottom;
|
||||
if (tile_y_overflow > 0) {
|
||||
if (tile_y_overflow > 0)
|
||||
tile_src_rect.set_height(tile_height - tile_y_overflow);
|
||||
}
|
||||
blit(IntPoint(tile_x, tile_y), bitmap, tile_src_rect);
|
||||
}
|
||||
}
|
||||
|
@ -2545,7 +2536,7 @@ void Gfx::Painter::draw_ui_text(Gfx::IntRect const& rect, StringView text, Gfx::
|
|||
float width = 0;
|
||||
for (auto it = utf8_view.begin(); it != utf8_view.end(); ++it) {
|
||||
if (utf8_view.byte_offset_of(it) >= underline_offset.value()) {
|
||||
int y = text_rect.bottom() + 1;
|
||||
int y = text_rect.bottom();
|
||||
int x1 = text_rect.left() + width;
|
||||
int x2 = x1 + font.glyph_or_emoji_width(it);
|
||||
draw_line({ x1, y }, { x2, y }, color);
|
||||
|
|
|
@ -15,8 +15,8 @@ namespace Gfx {
|
|||
template<typename T>
|
||||
void Point<T>::constrain(Rect<T> const& rect)
|
||||
{
|
||||
m_x = AK::clamp<T>(x(), rect.left(), rect.right());
|
||||
m_y = AK::clamp<T>(y(), rect.top(), rect.bottom());
|
||||
m_x = AK::clamp<T>(x(), rect.left(), rect.right() - 1);
|
||||
m_y = AK::clamp<T>(y(), rect.top(), rect.bottom() - 1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2021-2022, Sam Atkins <atkinssj@serenityos.org>
|
||||
* Copyright (c) 2022, Jelle Raaijmakers <jelle@gmta.nl>
|
||||
* Copyright (c) 2022-2023, Jelle Raaijmakers <jelle@gmta.nl>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -9,6 +9,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <AK/Format.h>
|
||||
#include <AK/Vector.h>
|
||||
#include <LibGfx/AffineTransform.h>
|
||||
#include <LibGfx/Line.h>
|
||||
#include <LibGfx/Orientation.h>
|
||||
|
@ -19,12 +20,6 @@
|
|||
|
||||
namespace Gfx {
|
||||
|
||||
template<typename T>
|
||||
T abst(T value)
|
||||
{
|
||||
return value < 0 ? -value : value;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
class Rect {
|
||||
public:
|
||||
|
@ -291,17 +286,17 @@ public:
|
|||
|
||||
[[nodiscard]] bool contains_vertically(T y) const
|
||||
{
|
||||
return y >= top() && y <= bottom();
|
||||
return y >= top() && y < bottom();
|
||||
}
|
||||
|
||||
[[nodiscard]] bool contains_horizontally(T x) const
|
||||
{
|
||||
return x >= left() && x <= right();
|
||||
return x >= left() && x < right();
|
||||
}
|
||||
|
||||
[[nodiscard]] bool contains(T x, T y) const
|
||||
{
|
||||
return x >= m_location.x() && x <= right() && y >= m_location.y() && y <= bottom();
|
||||
return contains_horizontally(x) && contains_vertically(y);
|
||||
}
|
||||
|
||||
[[nodiscard]] ALWAYS_INLINE bool contains(Point<T> const& point) const
|
||||
|
@ -354,29 +349,14 @@ public:
|
|||
}
|
||||
|
||||
[[nodiscard]] ALWAYS_INLINE T left() const { return x(); }
|
||||
[[nodiscard]] ALWAYS_INLINE T right() const { return x() + width() - 1; }
|
||||
[[nodiscard]] ALWAYS_INLINE T right() const { return x() + width(); }
|
||||
[[nodiscard]] ALWAYS_INLINE T top() const { return y(); }
|
||||
[[nodiscard]] ALWAYS_INLINE T bottom() const { return y() + height() - 1; }
|
||||
[[nodiscard]] ALWAYS_INLINE T bottom() const { return y() + height(); }
|
||||
|
||||
ALWAYS_INLINE void set_left(T left)
|
||||
{
|
||||
set_x(left);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void set_top(T top)
|
||||
{
|
||||
set_y(top);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void set_right(T right)
|
||||
{
|
||||
set_width(right - x() + 1);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void set_bottom(T bottom)
|
||||
{
|
||||
set_height(bottom - y() + 1);
|
||||
}
|
||||
ALWAYS_INLINE void set_left(T left) { set_x(left); }
|
||||
ALWAYS_INLINE void set_top(T top) { set_y(top); }
|
||||
ALWAYS_INLINE void set_right(T right) { set_width(right - x()); }
|
||||
ALWAYS_INLINE void set_bottom(T bottom) { set_height(bottom - y()); }
|
||||
|
||||
void set_right_without_resize(T new_right)
|
||||
{
|
||||
|
@ -392,20 +372,20 @@ public:
|
|||
|
||||
[[nodiscard]] bool intersects_vertically(Rect<T> const& other) const
|
||||
{
|
||||
return top() <= other.bottom() && other.top() <= bottom();
|
||||
return top() < other.bottom() && other.top() < bottom();
|
||||
}
|
||||
|
||||
[[nodiscard]] bool intersects_horizontally(Rect<T> const& other) const
|
||||
{
|
||||
return left() <= other.right() && other.left() <= right();
|
||||
return left() < other.right() && other.left() < right();
|
||||
}
|
||||
|
||||
[[nodiscard]] bool intersects(Rect<T> const& other) const
|
||||
{
|
||||
return left() <= other.right()
|
||||
&& other.left() <= right()
|
||||
&& top() <= other.bottom()
|
||||
&& other.top() <= bottom();
|
||||
return left() < other.right()
|
||||
&& other.left() < right()
|
||||
&& top() < other.bottom()
|
||||
&& other.top() < bottom();
|
||||
}
|
||||
|
||||
template<typename Container>
|
||||
|
@ -445,25 +425,25 @@ public:
|
|||
x(),
|
||||
y(),
|
||||
width(),
|
||||
hammer.y() - y()
|
||||
hammer.y() - y(),
|
||||
};
|
||||
Rect<T> bottom_shard {
|
||||
x(),
|
||||
hammer.y() + hammer.height(),
|
||||
hammer.bottom(),
|
||||
width(),
|
||||
(y() + height()) - (hammer.y() + hammer.height())
|
||||
bottom() - hammer.bottom(),
|
||||
};
|
||||
Rect<T> left_shard {
|
||||
x(),
|
||||
max(hammer.y(), y()),
|
||||
hammer.x() - x(),
|
||||
min((hammer.y() + hammer.height()), (y() + height())) - max(hammer.y(), y())
|
||||
min(hammer.bottom(), bottom()) - max(hammer.y(), y()),
|
||||
};
|
||||
Rect<T> right_shard {
|
||||
hammer.x() + hammer.width(),
|
||||
hammer.right(),
|
||||
max(hammer.y(), y()),
|
||||
right() - hammer.right(),
|
||||
min((hammer.y() + hammer.height()), (y() + height())) - max(hammer.y(), y())
|
||||
min(hammer.bottom(), bottom()) - max(hammer.y(), y()),
|
||||
};
|
||||
if (!top_shard.is_empty())
|
||||
pieces.unchecked_append(top_shard);
|
||||
|
@ -505,10 +485,10 @@ public:
|
|||
return;
|
||||
}
|
||||
|
||||
m_location.set_x(l);
|
||||
m_location.set_y(t);
|
||||
m_size.set_width((r - l) + 1);
|
||||
m_size.set_height((b - t) + 1);
|
||||
set_x(l);
|
||||
set_y(t);
|
||||
set_right(r);
|
||||
set_bottom(b);
|
||||
}
|
||||
|
||||
[[nodiscard]] static Rect<T> centered_on(Point<T> const& center, Size<T> const& size)
|
||||
|
@ -518,7 +498,7 @@ public:
|
|||
|
||||
[[nodiscard]] static Rect<T> from_two_points(Point<T> const& a, Point<T> const& b)
|
||||
{
|
||||
return { min(a.x(), b.x()), min(a.y(), b.y()), abst(a.x() - b.x()), abst(a.y() - b.y()) };
|
||||
return { min(a.x(), b.x()), min(a.y(), b.y()), AK::abs(a.x() - b.x()), AK::abs(a.y() - b.y()) };
|
||||
}
|
||||
|
||||
[[nodiscard]] static Rect<T> intersection(Rect<T> const& a, Rect<T> const& b)
|
||||
|
@ -541,18 +521,18 @@ public:
|
|||
if (auto point = line.intersected({ top_left(), top_right() }); point.has_value())
|
||||
points.append({ point.value().x(), y() });
|
||||
if (auto point = line.intersected({ bottom_left(), bottom_right() }); point.has_value()) {
|
||||
points.append({ point.value().x(), bottom() });
|
||||
points.append({ point.value().x(), bottom() - 1 });
|
||||
if (points.size() == 2)
|
||||
return points;
|
||||
}
|
||||
if (height() > 2) {
|
||||
if (auto point = line.intersected({ { x(), y() + 1 }, { x(), bottom() - 1 } }); point.has_value()) {
|
||||
if (auto point = line.intersected({ { x(), y() + 1 }, { x(), bottom() - 2 } }); point.has_value()) {
|
||||
points.append({ x(), point.value().y() });
|
||||
if (points.size() == 2)
|
||||
return points;
|
||||
}
|
||||
if (auto point = line.intersected({ { right(), y() + 1 }, { right(), bottom() - 1 } }); point.has_value())
|
||||
points.append({ right(), point.value().y() });
|
||||
if (auto point = line.intersected({ { right() - 1, y() + 1 }, { right() - 1, bottom() - 2 } }); point.has_value())
|
||||
points.append({ right() - 1, point.value().y() });
|
||||
}
|
||||
return points;
|
||||
}
|
||||
|
@ -560,11 +540,11 @@ public:
|
|||
template<typename U = T>
|
||||
[[nodiscard]] Gfx::Rect<U> interpolated_to(Gfx::Rect<T> const& to, float factor) const
|
||||
{
|
||||
VERIFY(factor >= 0.0f);
|
||||
VERIFY(factor <= 1.0f);
|
||||
if (factor == 0.0f)
|
||||
VERIFY(factor >= 0.f);
|
||||
VERIFY(factor <= 1.f);
|
||||
if (factor == 0.f)
|
||||
return *this;
|
||||
if (factor == 1.0f)
|
||||
if (factor == 1.f)
|
||||
return to;
|
||||
if (this == &to)
|
||||
return *this;
|
||||
|
@ -572,7 +552,7 @@ public:
|
|||
auto interpolated_top = round_to<U>(mix<float>(y(), to.y(), factor));
|
||||
auto interpolated_right = round_to<U>(mix<float>(right(), to.right(), factor));
|
||||
auto interpolated_bottom = round_to<U>(mix<float>(bottom(), to.bottom(), factor));
|
||||
return { interpolated_left, interpolated_top, interpolated_right - interpolated_left + 1, interpolated_bottom - interpolated_top + 1 };
|
||||
return { interpolated_left, interpolated_top, interpolated_right - interpolated_left, interpolated_bottom - interpolated_top };
|
||||
}
|
||||
|
||||
[[nodiscard]] float center_point_distance_to(Rect<T> const& other) const
|
||||
|
@ -596,7 +576,7 @@ public:
|
|||
{
|
||||
auto points = closest_outside_center_points(other);
|
||||
if (points.is_empty())
|
||||
return 0.0;
|
||||
return 0.f;
|
||||
return Line { points[0], points[0] }.length();
|
||||
}
|
||||
|
||||
|
@ -679,8 +659,8 @@ public:
|
|||
check_distance({ top_left(), top_right() });
|
||||
check_distance({ bottom_left(), bottom_right() });
|
||||
if (height() > 2) {
|
||||
check_distance({ { x(), y() + 1 }, { x(), bottom() - 1 } });
|
||||
check_distance({ { right(), y() + 1 }, { right(), bottom() - 1 } });
|
||||
check_distance({ { x(), y() + 1 }, { x(), bottom() - 2 } });
|
||||
check_distance({ { right() - 1, y() + 1 }, { right() - 1, bottom() - 2 } });
|
||||
}
|
||||
VERIFY(closest_point.has_value());
|
||||
VERIFY(side(closest_point.value()) != Side::None);
|
||||
|
@ -699,23 +679,23 @@ public:
|
|||
if (part.x() < other_rect.x()) {
|
||||
if (part.y() < other_rect.y())
|
||||
m_top_left = true;
|
||||
if ((part.y() >= other_rect.y() && part.y() < other_rect.bottom()) || (part.y() <= other_rect.bottom() && part.bottom() > other_rect.y()))
|
||||
if ((part.y() >= other_rect.y() && part.y() < other_rect.bottom() - 1) || (part.y() < other_rect.bottom() && part.bottom() - 1 > other_rect.y()))
|
||||
m_left = true;
|
||||
if (part.y() >= other_rect.bottom() || part.bottom() > other_rect.y())
|
||||
if (part.y() >= other_rect.bottom() - 1 || part.bottom() - 1 > other_rect.y())
|
||||
m_bottom_left = true;
|
||||
}
|
||||
if (part.x() >= other_rect.x() || part.right() > other_rect.x()) {
|
||||
if (part.x() >= other_rect.x() || part.right() - 1 > other_rect.x()) {
|
||||
if (part.y() < other_rect.y())
|
||||
m_top = true;
|
||||
if (part.y() >= other_rect.bottom() || part.bottom() > other_rect.bottom())
|
||||
if (part.y() >= other_rect.bottom() - 1 || part.bottom() > other_rect.bottom())
|
||||
m_bottom = true;
|
||||
}
|
||||
if (part.x() >= other_rect.right() || part.right() > other_rect.right()) {
|
||||
if (part.x() >= other_rect.right() - 1 || part.right() > other_rect.right()) {
|
||||
if (part.y() < other_rect.y())
|
||||
m_top_right = true;
|
||||
if ((part.y() >= other_rect.y() && part.y() < other_rect.bottom()) || (part.y() <= other_rect.bottom() && part.bottom() > other_rect.y()))
|
||||
if ((part.y() >= other_rect.y() && part.y() < other_rect.bottom() - 1) || (part.y() < other_rect.bottom() && part.bottom() - 1 > other_rect.y()))
|
||||
m_right = true;
|
||||
if (part.y() >= other_rect.bottom() || part.bottom() > other_rect.y())
|
||||
if (part.y() >= other_rect.bottom() - 1 || part.bottom() - 1 > other_rect.y())
|
||||
m_bottom_right = true;
|
||||
}
|
||||
}
|
||||
|
@ -763,9 +743,9 @@ public:
|
|||
{
|
||||
if (is_empty())
|
||||
return Side::None;
|
||||
if (point.y() == y() || point.y() == bottom())
|
||||
return (point.x() >= x() && point.x() <= right()) ? (point.y() == y() ? Side::Top : Side::Bottom) : Side::None;
|
||||
if (point.x() == x() || point.x() == right())
|
||||
if (point.y() == y() || point.y() == bottom() - 1)
|
||||
return (point.x() >= x() && point.x() < right()) ? (point.y() == y() ? Side::Top : Side::Bottom) : Side::None;
|
||||
if (point.x() == x() || point.x() == right() - 1)
|
||||
return (point.y() > y() && point.y() < bottom()) ? (point.x() == x() ? Side::Left : Side::Right) : Side::None;
|
||||
return Side::None;
|
||||
}
|
||||
|
@ -778,7 +758,7 @@ public:
|
|||
case Side::Left:
|
||||
// Return the area in other that is to the left of this rect
|
||||
if (other.x() < x()) {
|
||||
if (other.right() >= x())
|
||||
if (other.right() > x())
|
||||
return { other.location(), { x() - other.x(), other.height() } };
|
||||
else
|
||||
return other;
|
||||
|
@ -787,7 +767,7 @@ public:
|
|||
case Side::Top:
|
||||
// Return the area in other that is above this rect
|
||||
if (other.y() < y()) {
|
||||
if (other.bottom() >= y())
|
||||
if (other.bottom() > y())
|
||||
return { other.location(), { other.width(), y() - other.y() } };
|
||||
else
|
||||
return other;
|
||||
|
@ -795,18 +775,18 @@ public:
|
|||
break;
|
||||
case Side::Right:
|
||||
// Return the area in other that is to the right of this rect
|
||||
if (other.right() >= x()) {
|
||||
if (other.x() <= right())
|
||||
return { { right() + 1, other.y() }, { other.width() - (right() - other.x()), other.height() } };
|
||||
if (other.right() > x()) {
|
||||
if (other.x() < right())
|
||||
return { { right(), other.y() }, { other.width() - (right() - 1 - other.x()), other.height() } };
|
||||
else
|
||||
return other;
|
||||
}
|
||||
break;
|
||||
case Side::Bottom:
|
||||
// Return the area in other that is below this rect
|
||||
if (other.bottom() >= y()) {
|
||||
if (other.y() <= bottom())
|
||||
return { { other.x(), bottom() + 1 }, { other.width(), other.height() - (bottom() - other.y()) } };
|
||||
if (other.bottom() > y()) {
|
||||
if (other.y() < bottom())
|
||||
return { { other.x(), bottom() }, { other.width(), other.height() - (bottom() - 1 - other.y()) } };
|
||||
else
|
||||
return other;
|
||||
}
|
||||
|
@ -878,10 +858,10 @@ public:
|
|||
return false;
|
||||
if (intersects(other))
|
||||
return false;
|
||||
if (other.x() + other.width() == x() || other.x() == x() + width())
|
||||
return max(top(), other.top()) <= min(bottom(), other.bottom());
|
||||
if (other.y() + other.height() == y() || other.y() == y() + height())
|
||||
return max(left(), other.left()) <= min(right(), other.right());
|
||||
if (other.right() == x() || other.x() == right())
|
||||
return max(top(), other.top()) < min(bottom(), other.bottom());
|
||||
if (other.bottom() == y() || other.y() == bottom())
|
||||
return max(left(), other.left()) < min(right(), other.right());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -923,7 +903,7 @@ public:
|
|||
set_location(other.location());
|
||||
return;
|
||||
case TextAlignment::TopRight:
|
||||
set_x(other.x() + other.width() - width());
|
||||
set_x(other.right() - width());
|
||||
set_y(other.y());
|
||||
return;
|
||||
case TextAlignment::CenterLeft:
|
||||
|
@ -931,20 +911,20 @@ public:
|
|||
center_vertically_within(other);
|
||||
return;
|
||||
case TextAlignment::CenterRight:
|
||||
set_x(other.x() + other.width() - width());
|
||||
set_x(other.right() - width());
|
||||
center_vertically_within(other);
|
||||
return;
|
||||
case TextAlignment::BottomCenter:
|
||||
center_horizontally_within(other);
|
||||
set_y(other.y() + other.height() - height());
|
||||
set_y(other.bottom() - height());
|
||||
return;
|
||||
case TextAlignment::BottomLeft:
|
||||
set_x(other.x());
|
||||
set_y(other.y() + other.height() - height());
|
||||
set_y(other.bottom() - height());
|
||||
return;
|
||||
case TextAlignment::BottomRight:
|
||||
set_x(other.x() + other.width() - width());
|
||||
set_y(other.y() + other.height() - height());
|
||||
set_x(other.right() - width());
|
||||
set_y(other.bottom() - height());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1036,8 +1016,8 @@ using FloatRect = Rect<float>;
|
|||
{
|
||||
int x1 = floorf(float_rect.x());
|
||||
int y1 = floorf(float_rect.y());
|
||||
int x2 = ceilf(float_rect.x() + float_rect.width());
|
||||
int y2 = ceilf(float_rect.y() + float_rect.height());
|
||||
int x2 = ceilf(float_rect.right());
|
||||
int y2 = ceilf(float_rect.bottom());
|
||||
return Gfx::IntRect::from_two_points({ x1, y1 }, { x2, y2 });
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue