diff --git a/Widgets/Painter.cpp b/Widgets/Painter.cpp index 3cdd982a32..3fbe0993aa 100644 --- a/Widgets/Painter.cpp +++ b/Widgets/Painter.cpp @@ -4,6 +4,7 @@ #include "Font.h" #include "Window.h" #include +#include #include Painter::Painter(Widget& widget) @@ -17,6 +18,9 @@ Painter::Painter(Widget& widget) m_translation.setX(widget.x()); m_translation.setY(widget.y()); } + + m_clipRect.setWidth(AbstractScreen::the().width()); + m_clipRect.setHeight(AbstractScreen::the().height()); } Painter::~Painter() @@ -36,9 +40,9 @@ void Painter::fillRect(const Rect& rect, Color color) Rect r = rect; r.moveBy(m_translation); - for (int y = r.top(); y < r.bottom(); ++y) { + for (int y = max(r.top(), m_clipRect.top()); y < min(r.bottom(), m_clipRect.bottom()); ++y) { dword* bits = scanline(y); - for (int x = r.left(); x < r.right(); ++x) { + for (int x = max(r.left(), m_clipRect.left()); x < min(r.right(), m_clipRect.right()); ++x) { bits[x] = color.value(); } } @@ -49,15 +53,17 @@ void Painter::drawRect(const Rect& rect, Color color) Rect r = rect; r.moveBy(m_translation); - for (int y = r.top(); y < r.bottom(); ++y) { + for (int y = max(r.top(), m_clipRect.top()); y < min(r.bottom(), m_clipRect.bottom()); ++y) { dword* bits = scanline(y); if (y == r.top() || y == (r.bottom() - 1)) { - for (int x = r.left(); x < r.right(); ++x) { + for (int x = max(r.left(), m_clipRect.left()); x < min(r.right(), m_clipRect.right()); ++x) { bits[x] = color.value(); } } else { - bits[r.left()] = color.value(); - bits[r.right() - 1] = color.value(); + if (r.left() >= m_clipRect.left() && r.left() < m_clipRect.right()) + bits[r.left()] = color.value(); + if (r.right() >= m_clipRect.left() && r.right() < m_clipRect.right()) + bits[r.right() - 1] = color.value(); } } } @@ -67,15 +73,17 @@ void Painter::xorRect(const Rect& rect, Color color) Rect r = rect; r.moveBy(m_translation); - for (int y = r.top(); y < r.bottom(); ++y) { + for (int y = max(r.top(), m_clipRect.top()); y < min(r.bottom(), m_clipRect.bottom()); ++y) { dword* bits = scanline(y); if (y == r.top() || y == (r.bottom() - 1)) { - for (int x = r.left(); x < r.right(); ++x) { + for (int x = max(r.left(), m_clipRect.left()); x < min(r.right(), m_clipRect.right()); ++x) { bits[x] ^= color.value(); } } else { - bits[r.left()] ^= color.value(); - bits[r.right() - 1] ^= color.value(); + if (r.left() >= m_clipRect.left() && r.left() < m_clipRect.right()) + bits[r.left()] ^= color.value(); + if (r.right() >= m_clipRect.left() && r.right() < m_clipRect.right()) + bits[r.right() - 1] ^= color.value(); } } } @@ -86,12 +94,16 @@ void Painter::drawBitmap(const Point& p, const CBitmap& bitmap, Color color) point.moveBy(m_translation); for (unsigned row = 0; row < bitmap.height(); ++row) { int y = point.y() + row; - int x = point.x(); + if (y < m_clipRect.top() || y >= m_clipRect.bottom()) + break; dword* bits = scanline(y); for (unsigned j = 0; j < bitmap.width(); ++j) { + int x = point.x() + j; + if (x < m_clipRect.left() || x >= m_clipRect.right()) + break; char fc = bitmap.bits()[row * bitmap.width() + j]; if (fc == '#') - bits[x + j] = color.value(); + bits[x] = color.value(); } } } @@ -129,6 +141,8 @@ void Painter::drawPixel(const Point& p, Color color) { auto point = p; point.moveBy(m_translation); + if (!m_clipRect.contains(point)) + return; scanline(point.y())[point.x()] = color.value(); } @@ -142,10 +156,13 @@ void Painter::drawLine(const Point& p1, const Point& p2, Color color) // Special case: vertical line. if (point1.x() == point2.x()) { + const int x = point1.x(); + if (x < m_clipRect.left() || x >= m_clipRect.right()) + return; if (point1.y() > point2.y()) std::swap(point1, point2); - for (int y = point1.y(); y <= point2.y(); ++y) - scanline(y)[point1.x()] = color.value(); + for (int y = max(point1.y(), m_clipRect.top()); y <= min(point2.y(), m_clipRect.bottom()); ++y) + scanline(y)[x] = color.value(); return; } @@ -154,14 +171,20 @@ void Painter::drawLine(const Point& p1, const Point& p2, Color color) // Special case: horizontal line. if (point1.y() == point2.y()) { - if (point1.y() > point2.y()) + const int y = point1.y(); + if (y < m_clipRect.top() || y >= m_clipRect.bottom()) + return; + if (point1.x() > point2.x()) std::swap(point1, point2); auto* pixels = scanline(point1.y()); - for (int x = point1.x(); x <= point2.x(); ++x) + for (int x = max(point1.x(), m_clipRect.left()); x <= min(point2.x(), m_clipRect.right()); ++x) pixels[x] = color.value(); return; } + // FIXME: Implement clipping below. + ASSERT_NOT_REACHED(); + const double dx = point2.x() - point1.x(); const double dy = point2.y() - point1.y(); const double deltaError = fabs(dy / dx); diff --git a/Widgets/Painter.h b/Widgets/Painter.h index bc53725a7b..11b6aa7600 100644 --- a/Widgets/Painter.h +++ b/Widgets/Painter.h @@ -30,4 +30,6 @@ private: Widget& m_widget; Font& m_font; Point m_translation; + + Rect m_clipRect; }; diff --git a/Widgets/Rect.h b/Widgets/Rect.h index 98b0d865ff..e9f638ada4 100644 --- a/Widgets/Rect.h +++ b/Widgets/Rect.h @@ -42,7 +42,7 @@ public: bool contains(int x, int y) const { - return x >= m_location.x() && x <= right() && y >= m_location.y() && y <= bottom(); + return x >= m_location.x() && x < right() && y >= m_location.y() && y < bottom(); } bool contains(const Point& point) const diff --git a/Widgets/TerminalWidget.cpp b/Widgets/TerminalWidget.cpp index 7eaff9420e..16c62e43cf 100644 --- a/Widgets/TerminalWidget.cpp +++ b/Widgets/TerminalWidget.cpp @@ -133,6 +133,9 @@ void TerminalWidget::onReceive(byte ch) at(m_cursorRow, m_cursorColumn).character = ' '; } break; + case 27: + printf("TerminalWidget: got escape!\n"); + break; default: addChar(ch); break;