summaryrefslogtreecommitdiff
path: root/SharedGraphics
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-05-07 17:01:55 +0200
committerAndreas Kling <awesomekling@gmail.com>2019-05-07 17:01:55 +0200
commite8d395b14dff73e0e0c271e7d412e05ae50c5539 (patch)
tree27315175b57cf43007f0da04ea5696291048361b /SharedGraphics
parent4f77b4e5bce8bdeca9f33091531ad2db19832ea9 (diff)
downloadserenity-e8d395b14dff73e0e0c271e7d412e05ae50c5539.zip
Painter: Support diagonal lines with dy>dx, and apply clipping as well.
Diffstat (limited to 'SharedGraphics')
-rw-r--r--SharedGraphics/Painter.cpp73
1 files changed, 49 insertions, 24 deletions
diff --git a/SharedGraphics/Painter.cpp b/SharedGraphics/Painter.cpp
index 34b872d429..c713415841 100644
--- a/SharedGraphics/Painter.cpp
+++ b/SharedGraphics/Painter.cpp
@@ -478,6 +478,8 @@ void Painter::set_pixel(const Point& p, Color color)
void Painter::draw_line(const Point& p1, const Point& p2, Color color)
{
+ auto clip_rect = this->clip_rect();
+
auto point1 = p1;
point1.move_by(state().translation);
@@ -487,37 +489,34 @@ void Painter::draw_line(const Point& p1, const Point& p2, Color color)
// Special case: vertical line.
if (point1.x() == point2.x()) {
const int 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())
+ 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 min_y = max(point1.y(), clip_rect.top());
+ int max_y = min(point2.y(), clip_rect.bottom());
for (int y = min_y; y <= max_y; ++y)
set_pixel_with_draw_op(m_target->scanline(y)[x], color);
return;
}
- if (point1.x() > point2.x())
- swap(point1, point2);
-
// Special case: horizontal line.
if (point1.y() == point2.y()) {
const int 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())
+ 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 min_x = max(point1.x(), clip_rect.left());
+ int max_x = min(point2.x(), clip_rect.right());
auto* pixels = m_target->scanline(point1.y());
if (draw_op() == DrawOp::Copy) {
fast_dword_fill(pixels + min_x, color.value(), max_x - min_x + 1);
@@ -528,21 +527,47 @@ void Painter::draw_line(const Point& p1, const Point& p2, Color color)
return;
}
- // FIXME: Implement clipping below.
+ const double adx = abs(point2.x() - point1.x());
+ const double ady = abs(point2.y() - point1.y());
+
+ if (adx > ady) {
+ if (point1.x() > point2.x())
+ swap(point1, point2);
+ } else {
+ if (point1.y() > point2.y())
+ swap(point1, point2);
+ }
+ // FIXME: Implement clipping below.
const double dx = point2.x() - point1.x();
const double dy = point2.y() - point1.y();
- const double delta_error = fabs(dy / dx);
double error = 0;
- const double y_step = dy == 0 ? 0 : (dy > 0 ? 1 : -1);
-
- int y = point1.y();
- for (int x = point1.x(); x <= point2.x(); ++x) {
- m_target->scanline(y)[x] = color.value();
- error += delta_error;
- if (error >= 0.5) {
- y = (double)y + y_step;
- error -= 1.0;
+
+ if (dx > dy) {
+ const double y_step = dy == 0 ? 0 : (dy > 0 ? 1 : -1);
+ const double delta_error = fabs(dy / dx);
+ int y = point1.y();
+ for (int x = point1.x(); x <= point2.x(); ++x) {
+ if (clip_rect.contains(x, y))
+ m_target->scanline(y)[x] = color.value();
+ error += delta_error;
+ if (error >= 0.5) {
+ y = (double)y + y_step;
+ error -= 1.0;
+ }
+ }
+ } else {
+ const double x_step = dx == 0 ? 0 : (dx > 0 ? 1 : -1);
+ const double delta_error = fabs(dx / dy);
+ int x = point1.x();
+ for (int y = point1.y(); y <= point2.y(); ++y) {
+ if (clip_rect.contains(x, y))
+ m_target->scanline(y)[x] = color.value();
+ error += delta_error;
+ if (error >= 0.5) {
+ x = (double)x + x_step;
+ error -= 1.0;
+ }
}
}
}