diff options
author | frosch <frosch@openttd.org> | 2015-06-28 15:50:13 +0000 |
---|---|---|
committer | frosch <frosch@openttd.org> | 2015-06-28 15:50:13 +0000 |
commit | a65a194416421750110b87da97787b57eb66fe98 (patch) | |
tree | 2c77e5abac761e7ea4bbbd5c9f1f95960f919d5c /src | |
parent | bddcd33ed7220bb4168334d01f2b23f53196f758 (diff) | |
download | openttd-a65a194416421750110b87da97787b57eb66fe98.tar.xz |
(svn r27322) -Fix: Clipping of inclined lines did not account for the 'horizontal width' being bigger than the 'real width'. (adf88)
Diffstat (limited to 'src')
-rw-r--r-- | src/gfx.cpp | 20 |
1 files changed, 13 insertions, 7 deletions
diff --git a/src/gfx.cpp b/src/gfx.cpp index 410a2ee96..aa55b29a2 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -195,20 +195,26 @@ static inline void GfxDoDrawLine(void *video, int x, int y, int x2, int y2, int int grade_y = y2 - y; int grade_x = x2 - x; + /* Clipping rectangle. Slightly extended so we can ignore the width of the line. */ + uint extra = CeilDiv(3 * width, 4); // not less then "width * sqrt(2) / 2" + Rect clip = { -extra, -extra, screen_width - 1 + extra, screen_height - 1 + extra }; + /* prevent integer overflows. */ int margin = 1; - while (INT_MAX / abs(grade_y) < max(abs(x), abs(screen_width - x))) { + while (INT_MAX / abs(grade_y) < max(abs(clip.left - x), abs(clip.right - x))) { grade_y /= 2; grade_x /= 2; margin *= 2; // account for rounding errors } - /* If the line is outside the screen on the same side at X positions 0 - * and screen_width, we don't need to draw anything. */ - int offset_0 = y - x * grade_y / grade_x; - int offset_width = y + (screen_width - x) * grade_y / grade_x; - if ((offset_0 > screen_height + width / 2 + margin && offset_width > screen_height + width / 2 + margin) || - (offset_0 < -width / 2 - margin && offset_width < -width / 2 - margin)) { + /* Imagine that the line is infinitely long and it intersects with + * infinitely long left and right edges of the clipping rectangle. + * If booth intersection points are outside the clipping rectangle + * and booth on the same side of it, we don't need to draw anything. */ + int left_isec_y = y + (clip.left - x) * grade_y / grade_x; + int right_isec_y = y + (clip.right - x) * grade_y / grade_x; + if ((left_isec_y > clip.bottom + margin && right_isec_y > clip.bottom + margin) || + (left_isec_y < clip.top - margin && right_isec_y < clip.top - margin)) { return; } |