diff options
-rw-r--r-- | SharedGraphics/Painter.cpp | 48 | ||||
-rw-r--r-- | SharedGraphics/Painter.h | 6 | ||||
-rw-r--r-- | SharedGraphics/Rect.cpp | 2 | ||||
-rw-r--r-- | SharedGraphics/Rect.h | 6 | ||||
-rw-r--r-- | Terminal/Terminal.cpp | 8 | ||||
-rw-r--r-- | Terminal/Terminal.h | 1 | ||||
-rw-r--r-- | WindowServer/WSWindowManager.cpp | 25 |
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); |