From 9bd98ceeab463176ebc113d674117dafdf8ef492 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Tue, 22 Jan 2019 21:16:21 +0000 Subject: [PATCH] Blitter: Move DrawLineGeneric to a separate file to fix OSX compilation --- projects/openttd_vs140.vcxproj | 1 + projects/openttd_vs140.vcxproj.filters | 3 + projects/openttd_vs141.vcxproj | 1 + projects/openttd_vs141.vcxproj.filters | 3 + source.list | 1 + src/blitter/32bpp_anim.cpp | 1 + src/blitter/32bpp_base.cpp | 1 + src/blitter/8bpp_base.cpp | 1 + src/blitter/base.hpp | 177 ---------------------- src/blitter/common.hpp | 197 +++++++++++++++++++++++++ 10 files changed, 209 insertions(+), 177 deletions(-) create mode 100644 src/blitter/common.hpp diff --git a/projects/openttd_vs140.vcxproj b/projects/openttd_vs140.vcxproj index b0ade6f29e..eba6ad01f6 100644 --- a/projects/openttd_vs140.vcxproj +++ b/projects/openttd_vs140.vcxproj @@ -1256,6 +1256,7 @@ + diff --git a/projects/openttd_vs140.vcxproj.filters b/projects/openttd_vs140.vcxproj.filters index 3e8cf9faaa..fa3313c427 100644 --- a/projects/openttd_vs140.vcxproj.filters +++ b/projects/openttd_vs140.vcxproj.filters @@ -2859,6 +2859,9 @@ Blitters + + Blitters + Blitters diff --git a/projects/openttd_vs141.vcxproj b/projects/openttd_vs141.vcxproj index 080c973eec..9f5595b4ec 100644 --- a/projects/openttd_vs141.vcxproj +++ b/projects/openttd_vs141.vcxproj @@ -1256,6 +1256,7 @@ + diff --git a/projects/openttd_vs141.vcxproj.filters b/projects/openttd_vs141.vcxproj.filters index 3e8cf9faaa..fa3313c427 100644 --- a/projects/openttd_vs141.vcxproj.filters +++ b/projects/openttd_vs141.vcxproj.filters @@ -2859,6 +2859,9 @@ Blitters + + Blitters + Blitters diff --git a/source.list b/source.list index a0524ae10b..747d9c5727 100644 --- a/source.list +++ b/source.list @@ -1004,6 +1004,7 @@ blitter/8bpp_simple.cpp blitter/8bpp_simple.hpp #end blitter/base.hpp +blitter/common.hpp blitter/factory.hpp blitter/null.cpp blitter/null.hpp diff --git a/src/blitter/32bpp_anim.cpp b/src/blitter/32bpp_anim.cpp index 2dcafac4d1..ef707cf3c3 100644 --- a/src/blitter/32bpp_anim.cpp +++ b/src/blitter/32bpp_anim.cpp @@ -13,6 +13,7 @@ #include "../video/video_driver.hpp" #include "../zoom_func.h" #include "32bpp_anim.hpp" +#include "common.hpp" #include "../table/sprites.h" diff --git a/src/blitter/32bpp_base.cpp b/src/blitter/32bpp_base.cpp index 74ac459059..bdf7c2bf90 100644 --- a/src/blitter/32bpp_base.cpp +++ b/src/blitter/32bpp_base.cpp @@ -11,6 +11,7 @@ #include "../stdafx.h" #include "32bpp_base.hpp" +#include "common.hpp" #include "../safeguards.h" diff --git a/src/blitter/8bpp_base.cpp b/src/blitter/8bpp_base.cpp index a599ddc77a..7609f956b3 100644 --- a/src/blitter/8bpp_base.cpp +++ b/src/blitter/8bpp_base.cpp @@ -12,6 +12,7 @@ #include "../stdafx.h" #include "../gfx_func.h" #include "8bpp_base.hpp" +#include "common.hpp" #include "../safeguards.h" diff --git a/src/blitter/base.hpp b/src/blitter/base.hpp index b15915c5ee..0f6257ee89 100644 --- a/src/blitter/base.hpp +++ b/src/blitter/base.hpp @@ -243,181 +243,4 @@ public: template void DrawLineGeneric(int x, int y, int x2, int y2, int screen_width, int screen_height, int width, int dash, SetPixelT set_pixel); }; -template -void Blitter::DrawLineGeneric(int x, int y, int x2, int y2, int screen_width, int screen_height, int width, int dash, SetPixelT set_pixel) -{ - int dy; - int dx; - int stepx; - int stepy; - - dy = (y2 - y) * 2; - if (dy < 0) { - dy = -dy; - stepy = -1; - } else { - stepy = 1; - } - - dx = (x2 - x) * 2; - if (dx < 0) { - dx = -dx; - stepx = -1; - } else { - stepx = 1; - } - - if (dx == 0 && dy == 0) { - /* The algorithm below cannot handle this special case; make it work at least for line width 1 */ - if (x >= 0 && x < screen_width && y >= 0 && y < screen_height) set_pixel(x, y); - return; - } - - int frac_diff = width * max(dx, dy); - if (width > 1) { - /* compute frac_diff = width * sqrt(dx*dx + dy*dy) - * Start interval: - * max(dx, dy) <= sqrt(dx*dx + dy*dy) <= sqrt(2) * max(dx, dy) <= 3/2 * max(dx, dy) */ - int64 frac_sq = ((int64) width) * ((int64) width) * (((int64) dx) * ((int64) dx) + ((int64) dy) * ((int64) dy)); - int frac_max = 3 * frac_diff / 2; - while (frac_diff < frac_max) { - int frac_test = (frac_diff + frac_max) / 2; - if (((int64) frac_test) * ((int64) frac_test) < frac_sq) { - frac_diff = frac_test + 1; - } else { - frac_max = frac_test - 1; - } - } - } - - int gap = dash; - if (dash == 0) dash = 1; - int dash_count = 0; - if (dx > dy) { - if (stepx < 0) { - std::swap(x, x2); - std::swap(y, y2); - stepy = -stepy; - } - if (x2 < 0 || x >= screen_width) return; - - int y_low = y; - int y_high = y; - int frac_low = dy - frac_diff / 2; - int frac_high = dy + frac_diff / 2; - - while (frac_low < -(dx / 2)) { - frac_low += dx; - y_low -= stepy; - } - while (frac_high >= dx / 2) { - frac_high -= dx; - y_high += stepy; - } - - if (x < 0) { - dash_count = (-x) % (dash + gap); - auto adjust_frac = [&](int64 frac, int &y_bound) -> int { - frac -= ((int64) dy) * ((int64) x); - if (frac >= 0) { - int quotient = frac / dx; - int remainder = frac % dx; - y_bound += (1 + quotient) * stepy; - frac = remainder - dx; - } - return frac; - }; - frac_low = adjust_frac(frac_low, y_low); - frac_high = adjust_frac(frac_high, y_high); - x = 0; - } - x2++; - if (x2 > screen_width) { - x2 = screen_width; - } - - while (x != x2) { - if (dash_count < dash) { - for (int y = y_low; y != y_high; y += stepy) { - if (y >= 0 && y < screen_height) set_pixel(x, y); - } - } - if (frac_low >= 0) { - y_low += stepy; - frac_low -= dx; - } - if (frac_high >= 0) { - y_high += stepy; - frac_high -= dx; - } - x++; - frac_low += dy; - frac_high += dy; - if (++dash_count >= dash + gap) dash_count = 0; - } - } else { - if (stepy < 0) { - std::swap(x, x2); - std::swap(y, y2); - stepx = -stepx; - } - if (y2 < 0 || y >= screen_height) return; - - int x_low = x; - int x_high = x; - int frac_low = dx - frac_diff / 2; - int frac_high = dx + frac_diff / 2; - - while (frac_low < -(dy / 2)) { - frac_low += dy; - x_low -= stepx; - } - while (frac_high >= dy / 2) { - frac_high -= dy; - x_high += stepx; - } - - if (y < 0) { - dash_count = (-y) % (dash + gap); - auto adjust_frac = [&](int64 frac, int &x_bound) -> int { - frac -= ((int64) dx) * ((int64) y); - if (frac >= 0) { - int quotient = frac / dy; - int remainder = frac % dy; - x_bound += (1 + quotient) * stepx; - frac = remainder - dy; - } - return frac; - }; - frac_low = adjust_frac(frac_low, x_low); - frac_high = adjust_frac(frac_high, x_high); - y = 0; - } - y2++; - if (y2 > screen_height) { - y2 = screen_height; - } - - while (y != y2) { - if (dash_count < dash) { - for (int x = x_low; x != x_high; x += stepx) { - if (x >= 0 && x < screen_width) set_pixel(x, y); - } - } - if (frac_low >= 0) { - x_low += stepx; - frac_low -= dy; - } - if (frac_high >= 0) { - x_high += stepx; - frac_high -= dy; - } - y++; - frac_low += dx; - frac_high += dx; - if (++dash_count >= dash + gap) dash_count = 0; - } - } -} - #endif /* BLITTER_BASE_HPP */ diff --git a/src/blitter/common.hpp b/src/blitter/common.hpp new file mode 100644 index 0000000000..ad3267c716 --- /dev/null +++ b/src/blitter/common.hpp @@ -0,0 +1,197 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file base.hpp Common functionality for all blitter implemenytations. */ + +#ifndef BLITTER_COMMON_HPP +#define BLITTER_COMMON_HPP + +#include "base.hpp" +#include "../core/math_func.hpp" + +#include + +template +void Blitter::DrawLineGeneric(int x, int y, int x2, int y2, int screen_width, int screen_height, int width, int dash, SetPixelT set_pixel) +{ + int dy; + int dx; + int stepx; + int stepy; + + dy = (y2 - y) * 2; + if (dy < 0) { + dy = -dy; + stepy = -1; + } else { + stepy = 1; + } + + dx = (x2 - x) * 2; + if (dx < 0) { + dx = -dx; + stepx = -1; + } else { + stepx = 1; + } + + if (dx == 0 && dy == 0) { + /* The algorithm below cannot handle this special case; make it work at least for line width 1 */ + if (x >= 0 && x < screen_width && y >= 0 && y < screen_height) set_pixel(x, y); + return; + } + + int frac_diff = width * max(dx, dy); + if (width > 1) { + /* compute frac_diff = width * sqrt(dx*dx + dy*dy) + * Start interval: + * max(dx, dy) <= sqrt(dx*dx + dy*dy) <= sqrt(2) * max(dx, dy) <= 3/2 * max(dx, dy) */ + int64 frac_sq = ((int64) width) * ((int64) width) * (((int64) dx) * ((int64) dx) + ((int64) dy) * ((int64) dy)); + int frac_max = 3 * frac_diff / 2; + while (frac_diff < frac_max) { + int frac_test = (frac_diff + frac_max) / 2; + if (((int64) frac_test) * ((int64) frac_test) < frac_sq) { + frac_diff = frac_test + 1; + } else { + frac_max = frac_test - 1; + } + } + } + + int gap = dash; + if (dash == 0) dash = 1; + int dash_count = 0; + if (dx > dy) { + if (stepx < 0) { + std::swap(x, x2); + std::swap(y, y2); + stepy = -stepy; + } + if (x2 < 0 || x >= screen_width) return; + + int y_low = y; + int y_high = y; + int frac_low = dy - frac_diff / 2; + int frac_high = dy + frac_diff / 2; + + while (frac_low < -(dx / 2)) { + frac_low += dx; + y_low -= stepy; + } + while (frac_high >= dx / 2) { + frac_high -= dx; + y_high += stepy; + } + + if (x < 0) { + dash_count = (-x) % (dash + gap); + auto adjust_frac = [&](int64 frac, int &y_bound) -> int { + frac -= ((int64) dy) * ((int64) x); + if (frac >= 0) { + int quotient = frac / dx; + int remainder = frac % dx; + y_bound += (1 + quotient) * stepy; + frac = remainder - dx; + } + return frac; + }; + frac_low = adjust_frac(frac_low, y_low); + frac_high = adjust_frac(frac_high, y_high); + x = 0; + } + x2++; + if (x2 > screen_width) { + x2 = screen_width; + } + + while (x != x2) { + if (dash_count < dash) { + for (int y = y_low; y != y_high; y += stepy) { + if (y >= 0 && y < screen_height) set_pixel(x, y); + } + } + if (frac_low >= 0) { + y_low += stepy; + frac_low -= dx; + } + if (frac_high >= 0) { + y_high += stepy; + frac_high -= dx; + } + x++; + frac_low += dy; + frac_high += dy; + if (++dash_count >= dash + gap) dash_count = 0; + } + } else { + if (stepy < 0) { + std::swap(x, x2); + std::swap(y, y2); + stepx = -stepx; + } + if (y2 < 0 || y >= screen_height) return; + + int x_low = x; + int x_high = x; + int frac_low = dx - frac_diff / 2; + int frac_high = dx + frac_diff / 2; + + while (frac_low < -(dy / 2)) { + frac_low += dy; + x_low -= stepx; + } + while (frac_high >= dy / 2) { + frac_high -= dy; + x_high += stepx; + } + + if (y < 0) { + dash_count = (-y) % (dash + gap); + auto adjust_frac = [&](int64 frac, int &x_bound) -> int { + frac -= ((int64) dx) * ((int64) y); + if (frac >= 0) { + int quotient = frac / dy; + int remainder = frac % dy; + x_bound += (1 + quotient) * stepx; + frac = remainder - dy; + } + return frac; + }; + frac_low = adjust_frac(frac_low, x_low); + frac_high = adjust_frac(frac_high, x_high); + y = 0; + } + y2++; + if (y2 > screen_height) { + y2 = screen_height; + } + + while (y != y2) { + if (dash_count < dash) { + for (int x = x_low; x != x_high; x += stepx) { + if (x >= 0 && x < screen_width) set_pixel(x, y); + } + } + if (frac_low >= 0) { + x_low += stepx; + frac_low -= dy; + } + if (frac_high >= 0) { + x_high += stepx; + frac_high -= dy; + } + y++; + frac_low += dx; + frac_high += dx; + if (++dash_count >= dash + gap) dash_count = 0; + } + } +} + +#endif /* BLITTER_COMMON_HPP */