From 1dae7f9f3255777e516cc999182cdca458a4451c Mon Sep 17 00:00:00 2001 From: Ted John Date: Wed, 14 Jun 2017 19:47:22 +0100 Subject: [PATCH] Move SDL_LoadBMP call to libopenrct2ui (#5616) --- src/openrct2-ui/UiContext.cpp | 66 ++++++++++++++++++++++++++++++ src/openrct2/Context.cpp | 5 +++ src/openrct2/Context.h | 1 + src/openrct2/ui/DummyUiContext.cpp | 3 ++ src/openrct2/ui/UiContext.h | 5 +++ src/openrct2/world/mapgen.c | 29 +++---------- 6 files changed, 86 insertions(+), 23 deletions(-) diff --git a/src/openrct2-ui/UiContext.cpp b/src/openrct2-ui/UiContext.cpp index 22a551d5b9..988feb218d 100644 --- a/src/openrct2-ui/UiContext.cpp +++ b/src/openrct2-ui/UiContext.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,7 @@ extern "C" #include #include #include + #include } using namespace OpenRCT2; @@ -574,6 +576,70 @@ public: return _windowManager; } + bool ReadBMP(void * * outPixels, uint32 * outWidth, uint32 * outHeight, const std::string &path) override + { + auto bitmap = SDL_LoadBMP(path.c_str()); + if (bitmap != nullptr) + { + sint32 numChannels = bitmap->format->BytesPerPixel; + if (numChannels < 3 || bitmap->format->BitsPerPixel < 24) + { + window_error_open(STR_HEIGHT_MAP_ERROR, STR_ERROR_24_BIT_BITMAP); + SDL_FreeSurface(bitmap); + return false; + } + + // Copy pixels over, then discard the surface + *outPixels = nullptr; + *outWidth = bitmap->w; + *outHeight = bitmap->h; + if (SDL_LockSurface(bitmap) == 0) + { + *outPixels = malloc(bitmap->w * bitmap->h * 4); + memset(*outPixels, 0xFF, bitmap->w * bitmap->h); + + auto src = (const uint8 *)bitmap->pixels; + auto dst = (uint8 *)*outPixels; + if (numChannels == 4) + { + for (sint32 y = 0; y < bitmap->h; y++) + { + memcpy(dst, src, bitmap->w); + src += bitmap->pitch; + dst += bitmap->w; + } + } + else + { + for (sint32 y = 0; y < bitmap->h; y++) + { + for (sint32 x = 0; x < bitmap->w; x++) + { + memcpy(dst, src, 3); + src += 3; + dst += 4; + } + src += bitmap->pitch - (bitmap->w * 3); + } + } + SDL_UnlockSurface(bitmap); + } + else + { + return false; + } + SDL_FreeSurface(bitmap); + return true; + } + else + { + log_warning("Failed to load bitmap: %s", SDL_GetError()); + window_error_open(STR_HEIGHT_MAP_ERROR, STR_ERROR_READING_BITMAP); + return false; + } + } + + private: void OnResize(sint32 width, sint32 height) { diff --git a/src/openrct2/Context.cpp b/src/openrct2/Context.cpp index 834f560ee5..7233ef1d1d 100644 --- a/src/openrct2/Context.cpp +++ b/src/openrct2/Context.cpp @@ -671,6 +671,11 @@ extern "C" windowManager->HandleKeyboard(isTitle); } + bool context_read_bmp(void * * outPixels, uint32 * outWidth, uint32 * outHeight, const utf8 * path) + { + return GetContext()->GetUiContext()->ReadBMP(outPixels, outWidth, outHeight, std::string(path)); + } + bool platform_open_common_file_dialog(utf8 * outFilename, file_dialog_desc * desc, size_t outSize) { try diff --git a/src/openrct2/Context.h b/src/openrct2/Context.h index 6e10a77e22..bb8980a695 100644 --- a/src/openrct2/Context.h +++ b/src/openrct2/Context.h @@ -129,6 +129,7 @@ extern "C" void context_set_cursor_trap(bool value); rct_window * context_open_window(rct_windowclass wc); void context_input_handle_keyboard(bool isTitle); + bool context_read_bmp(void * * outPixels, uint32 * outWidth, uint32 * outHeight, const utf8 * path); #ifdef __cplusplus } #endif diff --git a/src/openrct2/ui/DummyUiContext.cpp b/src/openrct2/ui/DummyUiContext.cpp index 3ca2c013ba..906bf0f6aa 100644 --- a/src/openrct2/ui/DummyUiContext.cpp +++ b/src/openrct2/ui/DummyUiContext.cpp @@ -76,6 +76,9 @@ namespace OpenRCT2 { namespace Ui { return _windowManager; } + + // Misc + bool ReadBMP(void * * outPixels, uint32 * outWidth, uint32 * outHeight, const std::string &path) override { return false; } }; IUiContext * CreateDummyUiContext() diff --git a/src/openrct2/ui/UiContext.h b/src/openrct2/ui/UiContext.h index df3c89f862..7ebf92ec35 100644 --- a/src/openrct2/ui/UiContext.h +++ b/src/openrct2/ui/UiContext.h @@ -131,6 +131,11 @@ namespace OpenRCT2 // In-game UI virtual IWindowManager * GetWindowManager() abstract; + + // Misc. + // HACK: This should either be implemented ourselves in libopenrct2 + // or the mapgen height map code is moved to libopenrct2ui. + virtual bool ReadBMP(void * * outPixels, uint32 * outWidth, uint32 * outHeight, const std::string &path) abstract; }; IUiContext * CreateDummyUiContext(); diff --git a/src/openrct2/world/mapgen.c b/src/openrct2/world/mapgen.c index 594226beb7..160f0f25d1 100644 --- a/src/openrct2/world/mapgen.c +++ b/src/openrct2/world/mapgen.c @@ -16,7 +16,8 @@ #include "../common.h" #include -#include + +#include "../Context.h" #include "../Imaging.h" #include "../core/Guard.hpp" #include "../game.h" @@ -805,31 +806,13 @@ bool mapgen_load_heightmap(const utf8 *path) pitch = width * numChannels; } else if (strcicmp(extension, ".bmp") == 0) { - SDL_Surface *bitmap = SDL_LoadBMP(path); - if (bitmap == NULL) { - log_warning("Failed to load bitmap: %s", SDL_GetError()); - window_error_open(STR_HEIGHT_MAP_ERROR, STR_ERROR_READING_BITMAP); + if (!context_read_bmp((void *)&pixels, &width, &height, path)) { + // ReadBMP contains window_error_open calls return false; } - width = bitmap->w; - height = bitmap->h; - numChannels = bitmap->format->BytesPerPixel; - pitch = bitmap->pitch; - - if (numChannels < 3 || bitmap->format->BitsPerPixel < 24) - { - window_error_open(STR_HEIGHT_MAP_ERROR, STR_ERROR_24_BIT_BITMAP); - SDL_FreeSurface(bitmap); - return false; - } - - // Copy pixels over, then discard the surface - SDL_LockSurface(bitmap); - pixels = malloc(height * bitmap->pitch); - memcpy(pixels, bitmap->pixels, height * bitmap->pitch); - SDL_UnlockSurface(bitmap); - SDL_FreeSurface(bitmap); + numChannels = 4; + pitch = width * numChannels; } else {