summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--SharedGraphics/Painter.cpp48
-rw-r--r--SharedGraphics/Painter.h6
-rw-r--r--SharedGraphics/Rect.cpp2
-rw-r--r--SharedGraphics/Rect.h6
-rw-r--r--Terminal/Terminal.cpp8
-rw-r--r--Terminal/Terminal.h1
-rw-r--r--WindowServer/WSWindowManager.cpp25
7 files changed, 61 insertions, 35 deletions
diff --git a/SharedGraphics/Painter.cpp b/SharedGraphics/Painter.cpp
index c3e9d54d00..59987601e0 100644
--- a/SharedGraphics/Painter.cpp
+++ b/SharedGraphics/Painter.cpp
@@ -56,42 +56,44 @@ void Painter::fill_rect(const Rect& a_rect, Color color)
}
}
-void Painter::draw_rect(const Rect& rect, Color color)
+void Painter::draw_rect(const Rect& a_rect, Color color)
{
- Rect r = rect;
- r.move_by(m_translation);
+ Rect rect = a_rect;
+ rect.move_by(m_translation);
+
+ auto clipped_rect = Rect::intersection(rect, m_clip_rect);
+ if (clipped_rect.is_empty())
+ return;
- int min_y = max(r.top(), m_clip_rect.top());
- int max_y = min(r.bottom(), m_clip_rect.bottom());
- int min_x = max(r.left(), m_clip_rect.left());
- int max_x = min(r.right(), m_clip_rect.right());
+ int min_y = clipped_rect.top();
+ int max_y = clipped_rect.bottom();
- if (r.top() >= min_y && r.top() <= max_y) {
- fast_dword_fill(m_target->scanline(r.top()) + min_x, color.value(), max_x - min_x + 1);
+ if (rect.top() >= clipped_rect.top() && rect.top() <= clipped_rect.bottom()) {
+ fast_dword_fill(m_target->scanline(rect.top()) + clipped_rect.left(), color.value(), clipped_rect.width());
++min_y;
}
- if (r.bottom() <= max_y && r.bottom() >= min_y) {
- fast_dword_fill(m_target->scanline(r.bottom()) + min_x, color.value(), max_x - min_x + 1);
+ if (rect.bottom() >= clipped_rect.top() && rect.bottom() <= clipped_rect.bottom()) {
+ fast_dword_fill(m_target->scanline(rect.bottom()) + clipped_rect.left(), color.value(), clipped_rect.width());
--max_y;
}
- bool draw_left_side = r.left() >= m_clip_rect.left() && r.left() <= m_clip_rect.right();
- bool draw_right_side = r.right() >= m_clip_rect.left() && r.right() <= m_clip_rect.right();
+ bool draw_left_side = rect.left() >= clipped_rect.left();
+ bool draw_right_side = rect.right() == clipped_rect.right();
if (draw_left_side && draw_right_side) {
// Specialized loop when drawing both sides.
for (int y = min_y; y <= max_y; ++y) {
auto* bits = m_target->scanline(y);
- bits[r.left()] = color.value();
- bits[r.right()] = color.value();
+ bits[rect.left()] = color.value();
+ bits[rect.right()] = color.value();
}
} else {
for (int y = min_y; y <= max_y; ++y) {
auto* bits = m_target->scanline(y);
if (draw_left_side)
- bits[r.left()] = color.value();
+ bits[rect.left()] = color.value();
if (draw_right_side)
- bits[r.right()] = color.value();
+ bits[rect.right()] = color.value();
}
}
}
@@ -103,12 +105,12 @@ void Painter::draw_bitmap(const Point& p, const CharacterBitmap& bitmap, Color c
for (unsigned row = 0; row < bitmap.height(); ++row) {
int y = point.y() + row;
if (y < m_clip_rect.top() || y > m_clip_rect.bottom())
- break;
+ continue;
auto* bits = m_target->scanline(y);
for (unsigned j = 0; j < bitmap.width(); ++j) {
int x = point.x() + j;
if (x < m_clip_rect.left() || x > m_clip_rect.right())
- break;
+ continue;
char fc = bitmap.bits()[row * bitmap.width() + j];
if (fc == '#')
bits[x] = color.value();
@@ -244,13 +246,13 @@ void Painter::draw_focus_rect(const Rect& rect)
draw_rect(focus_rect, Color(96, 96, 192));
}
-void Painter::blit(const Point& position, const GraphicsBitmap& source)
+void Painter::blit(const Point& position, const GraphicsBitmap& source, const Rect& src_rect)
{
- Rect dst_rect(position, source.size());
+ Rect dst_rect(position, src_rect.size());
dst_rect.intersect(m_clip_rect);
- RGBA32* dst = m_target->scanline(position.y()) + dst_rect.x();
- const RGBA32* src= source.scanline(0) + (dst_rect.x() - position.x());
+ RGBA32* dst = m_target->scanline(dst_rect.y()) + dst_rect.x();
+ const RGBA32* src = source.scanline(src_rect.top()) + src_rect.left();
const unsigned dst_skip = m_target->width();
const unsigned src_skip = source.width();
diff --git a/SharedGraphics/Painter.h b/SharedGraphics/Painter.h
index 5c66faf3a5..c8f3413802 100644
--- a/SharedGraphics/Painter.h
+++ b/SharedGraphics/Painter.h
@@ -28,7 +28,7 @@ public:
void set_pixel(const Point&, Color);
void draw_line(const Point&, const Point&, Color);
void draw_focus_rect(const Rect&);
- void blit(const Point&, const GraphicsBitmap&);
+ void blit(const Point&, const GraphicsBitmap&, const Rect& src_rect);
enum class TextAlignment { TopLeft, CenterLeft, Center };
void draw_text(const Rect&, const String&, TextAlignment = TextAlignment::TopLeft, Color = Color());
@@ -40,6 +40,10 @@ public:
void set_draw_op(DrawOp op) { m_draw_op = op; }
DrawOp draw_op() const { return m_draw_op; }
+ void set_clip_rect(const Rect& rect) { m_clip_rect = rect; }
+ void clear_clip_rect() { m_clip_rect = { 0, 0, 1024, 768 }; }
+ Rect clip_rect() const { return m_clip_rect; }
+
private:
void set_pixel_with_draw_op(dword& pixel, const Color&);
diff --git a/SharedGraphics/Rect.cpp b/SharedGraphics/Rect.cpp
index 5b01bf2e1e..ffbf59f1ef 100644
--- a/SharedGraphics/Rect.cpp
+++ b/SharedGraphics/Rect.cpp
@@ -8,7 +8,7 @@ void Rect::intersect(const Rect& other)
int t = max(top(), other.top());
int b = min(bottom(), other.bottom());
- if (l >= r || t >= b) {
+ if (l > r || t > b) {
m_location = { };
m_size = { };
return;
diff --git a/SharedGraphics/Rect.h b/SharedGraphics/Rect.h
index e99e6d6ded..6273559d1b 100644
--- a/SharedGraphics/Rect.h
+++ b/SharedGraphics/Rect.h
@@ -18,6 +18,12 @@ public:
, m_size(size)
{
}
+ Rect(const Rect& other)
+ : m_location(other.m_location)
+ , m_size(other.m_size)
+ {
+ }
+
Rect(const GUI_Rect&);
bool is_null() const
diff --git a/Terminal/Terminal.cpp b/Terminal/Terminal.cpp
index c01cd5708b..f74e8b0c8d 100644
--- a/Terminal/Terminal.cpp
+++ b/Terminal/Terminal.cpp
@@ -426,7 +426,6 @@ void Terminal::paint()
Rect rect { 0, 0, m_pixel_width, m_pixel_height };
Painter painter(*m_backing);
- bool need_full_invalidation = false;
memset(m_row_needs_invalidation, 0, rows() * sizeof(bool));
#ifdef FAST_SCROLL
@@ -440,7 +439,7 @@ void Terminal::paint()
m_backing->scanline(second_scanline),
scanlines_to_copy * m_pixel_width
);
- need_full_invalidation = true;
+ m_need_full_invalidation = true;
attribute_at(m_cursor_row - m_rows_to_scroll_backing_store, m_cursor_column).dirty = true;
}
m_rows_to_scroll_backing_store = 0;
@@ -472,12 +471,13 @@ void Terminal::paint()
m_row_needs_invalidation[m_cursor_row] = true;
if (m_belling) {
- need_full_invalidation = true;
+ m_need_full_invalidation = true;
painter.draw_rect(rect, Color::Red);
}
- if (need_full_invalidation) {
+ if (m_need_full_invalidation) {
invalidate_window();
+ m_need_full_invalidation = false;
return;
}
diff --git a/Terminal/Terminal.h b/Terminal/Terminal.h
index a13511af7d..13645293a3 100644
--- a/Terminal/Terminal.h
+++ b/Terminal/Terminal.h
@@ -101,6 +101,7 @@ private:
int m_line_height { 0 };
bool m_in_active_window { false };
+ bool m_need_full_invalidation { false };
RetainPtr<Font> m_font;
};
diff --git a/WindowServer/WSWindowManager.cpp b/WindowServer/WSWindowManager.cpp
index 182bc2a0be..8260ff2ffb 100644
--- a/WindowServer/WSWindowManager.cpp
+++ b/WindowServer/WSWindowManager.cpp
@@ -321,19 +321,32 @@ void WSWindowManager::compose()
return false;
};
- for (auto& r : dirty_rects) {
- if (any_window_contains_rect(r))
+ for (auto& dirty_rect : dirty_rects) {
+ if (any_window_contains_rect(dirty_rect)) {
continue;
- //dbgprintf("Repaint root %d,%d %dx%d\n", r.x(), r.y(), r.width(), r.height());
- m_back_painter->fill_rect(r, Color(0, 72, 96));
+ }
+ //dbgprintf("Repaint root %d,%d %dx%d\n", dirty_rect.x(), dirty_rect.y(), dirty_rect.width(), dirty_rect.height());
+ m_back_painter->fill_rect(dirty_rect, Color(0, 72, 96));
}
for (auto* window = m_windows_in_order.head(); window; window = window->next()) {
if (!window->backing())
continue;
if (!any_dirty_rect_intersects_window(*window))
continue;
- paint_window_frame(*window);
- m_back_painter->blit(window->position(), *window->backing());
+ for (auto& dirty_rect : dirty_rects) {
+ m_back_painter->set_clip_rect(dirty_rect);
+ paint_window_frame(*window);
+ Rect dirty_rect_in_window_coordinates = Rect::intersection(dirty_rect, window->rect());
+ if (dirty_rect_in_window_coordinates.is_empty())
+ continue;
+ dirty_rect_in_window_coordinates.set_x(dirty_rect_in_window_coordinates.x() - window->x());
+ dirty_rect_in_window_coordinates.set_y(dirty_rect_in_window_coordinates.y() - window->y());
+ auto dst = window->position();
+ dst.move_by(dirty_rect_in_window_coordinates.location());
+ m_back_painter->blit(dst, *window->backing(), dirty_rect_in_window_coordinates);
+ m_back_painter->clear_clip_rect();
+ }
+ m_back_painter->clear_clip_rect();
}
for (auto& r : dirty_rects)
flush(r);