Browse Source

Merge pull request #1527 from IvanSavenko/sdl_abstraction_iteration

SDL abstraction layer iteration
Ivan Savenko 2 years ago
parent
commit
885fad87f9
58 changed files with 518 additions and 513 deletions
  1. 2 2
      client/CMT.cpp
  2. 1 2
      client/CMakeLists.txt
  3. 9 7
      client/CMessage.cpp
  4. 4 4
      client/CPlayerInterface.cpp
  5. 2 0
      client/CServerHandler.cpp
  6. 3 0
      client/CVideoHandler.cpp
  7. 2 0
      client/ClientCommandManager.cpp
  8. 2 1
      client/Graphics.cpp
  9. 0 2
      client/StdInc.h
  10. 3 0
      client/battle/BattleInterfaceClasses.cpp
  11. 2 7
      client/battle/BattleProjectileController.cpp
  12. 4 4
      client/battle/BattleStacksController.cpp
  13. 3 0
      client/battle/BattleWindow.cpp
  14. 1 1
      client/battle/CreatureAnimation.cpp
  15. 2 0
      client/battle/CreatureAnimation.h
  16. 39 17
      client/gui/CAnimation.cpp
  17. 8 3
      client/gui/CAnimation.h
  18. 8 6
      client/gui/CGuiHandler.cpp
  19. 2 2
      client/gui/CGuiHandler.h
  20. 2 0
      client/gui/CIntObject.cpp
  21. 2 2
      client/gui/Canvas.cpp
  22. 2 1
      client/gui/Canvas.h
  23. 3 0
      client/gui/CursorHandler.cpp
  24. 10 13
      client/gui/Fonts.cpp
  25. 0 25
      client/gui/SDL_Compat.h
  26. 54 55
      client/gui/SDL_Extensions.cpp
  27. 15 11
      client/gui/SDL_Extensions.h
  28. 48 47
      client/gui/SDL_PixelAccess.h
  29. 4 4
      client/lobby/CBonusSelection.cpp
  30. 3 1
      client/lobby/CSelectionBase.cpp
  31. 1 0
      client/lobby/SelectionTab.cpp
  32. 1 4
      client/mainmenu/CMainMenu.cpp
  33. 7 7
      client/mapHandler.cpp
  34. 24 40
      client/widgets/AdventureMapClasses.cpp
  35. 5 5
      client/widgets/AdventureMapClasses.h
  36. 2 0
      client/widgets/Buttons.cpp
  37. 2 0
      client/widgets/Buttons.h
  38. 3 1
      client/widgets/CGarrisonInt.cpp
  39. 42 113
      client/widgets/Images.cpp
  40. 28 23
      client/widgets/Images.h
  41. 5 8
      client/widgets/TextControls.cpp
  42. 4 1
      client/widgets/TextControls.h
  43. 12 14
      client/windows/CAdvmapInterface.cpp
  44. 2 3
      client/windows/CAdvmapInterface.h
  45. 34 44
      client/windows/CCastleInterface.cpp
  46. 2 3
      client/windows/CCastleInterface.h
  47. 5 4
      client/windows/CSpellWindow.cpp
  48. 1 1
      client/windows/CSpellWindow.h
  49. 1 1
      client/windows/CTradeWindow.cpp
  50. 12 6
      client/windows/CWindowObject.cpp
  51. 3 2
      client/windows/GUIClasses.cpp
  52. 2 1
      client/windows/InfoWindows.cpp
  53. 1 0
      cmake_modules/VCMI_lib.cmake
  54. 9 9
      lib/CCreatureHandler.cpp
  55. 4 3
      lib/CCreatureHandler.h
  56. 62 0
      lib/Color.h
  57. 3 2
      lib/TerrainHandler.h
  58. 1 1
      mapeditor/maphandler.cpp

+ 2 - 2
client/CMT.cpp

@@ -713,7 +713,7 @@ static bool recreateWindow(int w, int h, int bpp, bool fullscreen, int displayIn
 	if(nullptr == mainWindow)
 	{
 #if defined(VCMI_ANDROID) || defined(VCMI_IOS)
-		auto createWindow = [displayIndex](Uint32 extraFlags) -> bool {
+		auto createWindow = [displayIndex](uint32_t extraFlags) -> bool {
 			mainWindow = SDL_CreateWindow(NAME.c_str(), SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex), SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex), 0, 0, SDL_WINDOW_FULLSCREEN | extraFlags);
 			return mainWindow != nullptr;
 		};
@@ -723,7 +723,7 @@ static bool recreateWindow(int w, int h, int bpp, bool fullscreen, int displayIn
 		SDL_SetHint(SDL_HINT_RETURN_KEY_HIDES_IME, "1");
 		SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "best");
 
-		Uint32 windowFlags = SDL_WINDOW_BORDERLESS | SDL_WINDOW_ALLOW_HIGHDPI;
+		uint32_t windowFlags = SDL_WINDOW_BORDERLESS | SDL_WINDOW_ALLOW_HIGHDPI;
 		if(!createWindow(windowFlags | SDL_WINDOW_METAL))
 		{
 			logGlobal->warn("Metal unavailable, using OpenGLES");

+ 1 - 2
client/CMakeLists.txt

@@ -110,9 +110,8 @@ set(client_HEADERS
 		gui/CIntObject.h
 		gui/Fonts.h
 		gui/TextAlignment.h
-		gui/SDL_Compat.h
 		gui/SDL_Extensions.h
-		gui/SDL_Pixels.h
+		gui/SDL_PixelAccess.h
 		gui/NotificationHandler.h
 		gui/InterfaceObjectConfigurable.h
 

+ 9 - 7
client/CMessage.cpp

@@ -22,6 +22,8 @@
 #include "widgets/Buttons.h"
 #include "widgets/TextControls.h"
 
+#include <SDL_surface.h>
+
 const int BETWEEN_COMPS_ROWS = 10;
 const int BEFORE_COMPONENTS = 30;
 const int BETWEEN_COMPS = 30;
@@ -64,7 +66,7 @@ namespace
 	std::array<std::unique_ptr<CAnimation>, PlayerColor::PLAYER_LIMIT_I> dialogBorders;
 	std::array<std::vector<std::shared_ptr<IImage>>, PlayerColor::PLAYER_LIMIT_I> piecesOfBox;
 
-	SDL_Surface * background = nullptr;//todo: should be CFilledTexture
+	std::shared_ptr<IImage> background;//todo: should be CFilledTexture
 }
 
 void CMessage::init()
@@ -84,27 +86,27 @@ void CMessage::init()
 		}
 	}
 
-	background = BitmapHandler::loadBitmap("DIBOXBCK.BMP");
+	background = IImage::createFromFile("DIBOXBCK.BMP");
 }
 
 void CMessage::dispose()
 {
 	for(auto & item : dialogBorders)
 		item.reset();
-	SDL_FreeSurface(background);
 }
 
 SDL_Surface * CMessage::drawDialogBox(int w, int h, PlayerColor playerColor)
 {
 	//prepare surface
-	SDL_Surface * ret = SDL_CreateRGBSurface(0, w, h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
-	for (int i=0; i<w; i+=background->w)//background
+	SDL_Surface * ret = CSDL_Ext::newSurface(w,h);
+	for (int i=0; i<w; i+=background->width())//background
 	{
-		for (int j=0; j<h; j+=background->h)
+		for (int j=0; j<h; j+=background->height())
 		{
-			CSDL_Ext::blitSurface(background, ret, Point(i,j));
+			background->draw(ret, i, j);
 		}
 	}
+
 	drawBorder(playerColor, ret, w, h);
 	return ret;
 }

+ 4 - 4
client/CPlayerInterface.cpp

@@ -63,12 +63,12 @@
 #include "../lib/CPathfinder.h"
 #include "../lib/RoadHandler.h"
 #include "../lib/TerrainHandler.h"
-#include <SDL_timer.h>
 #include "CServerHandler.h"
 // FIXME: only needed for CGameState::mutex
 #include "../lib/CGameState.h"
 #include "gui/NotificationHandler.h"
 
+#include <SDL_events.h>
 
 // The macro below is used to mark functions that are called by client when game state changes.
 // They all assume that CPlayerInterface::pim mutex is locked.
@@ -342,7 +342,7 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
 
 		auto unlockPim = vstd::makeUnlockGuard(*pim);
 		while(frameNumber == GH.mainFPSmng->getFrameNumber())
-			SDL_Delay(5);
+			boost::this_thread::sleep(boost::posix_time::milliseconds(5));
 	};
 
 	//first initializing done
@@ -1514,7 +1514,7 @@ void CPlayerInterface::centerView (int3 pos, int focusTime)
 		{
 			auto unlockPim = vstd::makeUnlockGuard(*pim);
 			IgnoreEvents ignore(*this);
-			SDL_Delay(focusTime);
+			boost::this_thread::sleep(boost::posix_time::milliseconds(focusTime));
 		}
 	}
 	CCS->curh->show();
@@ -2276,7 +2276,7 @@ void CPlayerInterface::waitForAllDialogs(bool unlockPim)
 	while(!dialogs.empty())
 	{
 		auto unlock = vstd::makeUnlockGuardIf(*pim, unlockPim);
-		SDL_Delay(5);
+		boost::this_thread::sleep(boost::posix_time::milliseconds(5));
 	}
 	waitWhileDialog(unlockPim);
 }

+ 2 - 0
client/CServerHandler.cpp

@@ -60,6 +60,8 @@
 #include <windows.h>
 #endif
 
+#include <SDL_events.h>
+
 template<typename T> class CApplyOnLobby;
 
 const std::string CServerHandler::localhostAddress{"127.0.0.1"};

+ 3 - 0
client/CVideoHandler.cpp

@@ -15,6 +15,9 @@
 #include "CPlayerInterface.h"
 #include "../lib/filesystem/Filesystem.h"
 
+#include <SDL_render.h>
+#include <SDL_events.h>
+
 extern CGuiHandler GH; //global gui handler
 
 #ifndef DISABLE_VIDEO

+ 2 - 0
client/ClientCommandManager.cpp

@@ -33,6 +33,8 @@
 #include "../lib/ScriptHandler.h"
 #endif
 
+#include <SDL_surface.h>
+
 void ClientCommandManager::handleGoSolo()
 {
 	Settings session = settings.write["session"];

+ 2 - 1
client/Graphics.cpp

@@ -22,7 +22,6 @@
 #include "../lib/filesystem/CBinaryReader.h"
 #include "gui/SDL_Extensions.h"
 #include "gui/CAnimation.h"
-#include <SDL_ttf.h>
 #include "../lib/CThreadHelper.h"
 #include "../lib/CModHandler.h"
 #include "CGameInfo.h"
@@ -37,6 +36,8 @@
 #include "../lib/mapObjects/CObjectHandler.h"
 #include "../lib/CHeroHandler.h"
 
+#include <SDL_surface.h>
+
 using namespace CSDL_Ext;
 
 Graphics * graphics = nullptr;

+ 0 - 2
client/StdInc.h

@@ -2,8 +2,6 @@
 
 #include "../Global.h"
 
-#include "gui/SDL_Compat.h"
-
 // This header should be treated as a pre compiled header file(PCH) in the compiler building settings.
 
 // Here you can add specific libraries and macros which are specific to this project.

+ 3 - 0
client/battle/BattleInterfaceClasses.cpp

@@ -48,6 +48,9 @@
 #include "../../lib/CondSh.h"
 #include "../../lib/mapObjects/CGTownInstance.h"
 
+#include <SDL_surface.h>
+#include <SDL_events.h>
+
 void BattleConsole::showAll(SDL_Surface * to)
 {
 	CIntObject::showAll(to);

+ 2 - 7
client/battle/BattleProjectileController.cpp

@@ -116,10 +116,7 @@ void ProjectileRay::show(Canvas & canvas)
 		for (size_t i = 0; i < rayConfig.size(); ++i)
 		{
 			auto ray = rayConfig[i];
-			SDL_Color beginColor{ ray.r1, ray.g1, ray.b1, ray.a1};
-			SDL_Color endColor  { ray.r2, ray.g2, ray.b2, ray.a2};
-
-			canvas.drawLine(Point(x1, y1 + i), Point(x2, y2+i), beginColor, endColor);
+			canvas.drawLine(Point(x1, y1 + i), Point(x2, y2+i), ray.start, ray.end);
 		}
 	}
 	else // draw in vertical axis
@@ -133,10 +130,8 @@ void ProjectileRay::show(Canvas & canvas)
 		for (size_t i = 0; i < rayConfig.size(); ++i)
 		{
 			auto ray = rayConfig[i];
-			SDL_Color beginColor{ ray.r1, ray.g1, ray.b1, ray.a1};
-			SDL_Color endColor  { ray.r2, ray.g2, ray.b2, ray.a2};
 
-			canvas.drawLine(Point(x1 + i, y1), Point(x2 + i, y2), beginColor, endColor);
+			canvas.drawLine(Point(x1 + i, y1), Point(x2 + i, y2), ray.start, ray.end);
 		}
 	}
 

+ 4 - 4
client/battle/BattleStacksController.cpp

@@ -89,10 +89,10 @@ BattleStacksController::BattleStacksController(BattleInterface & owner):
 	static const auto shifterNegative = ColorFilter::genRangeShifter( 0.f, 0.f, 0.f, 1.0f, 0.2f, 0.2f );
 	static const auto shifterNeutral  = ColorFilter::genRangeShifter( 0.f, 0.f, 0.f, 1.0f, 1.0f, 0.2f );
 
-	amountNormal->adjustPalette(shifterNormal);
-	amountPositive->adjustPalette(shifterPositive);
-	amountNegative->adjustPalette(shifterNegative);
-	amountEffNeutral->adjustPalette(shifterNeutral);
+	amountNormal->adjustPalette(shifterNormal, 0);
+	amountPositive->adjustPalette(shifterPositive, 0);
+	amountNegative->adjustPalette(shifterNegative, 0);
+	amountEffNeutral->adjustPalette(shifterNeutral, 0);
 
 	//Restore border color {255, 231, 132, 255} to its original state
 	amountNormal->resetPalette(26);

+ 3 - 0
client/battle/BattleWindow.cpp

@@ -36,6 +36,9 @@
 #include "../../lib/CConfigHandler.h"
 #include "../../lib/filesystem/ResourceID.h"
 
+#include <SDL_surface.h>
+#include <SDL_events.h>
+
 BattleWindow::BattleWindow(BattleInterface & owner):
 	owner(owner)
 {

+ 1 - 1
client/battle/CreatureAnimation.cpp

@@ -345,7 +345,7 @@ void CreatureAnimation::nextFrame(Canvas & canvas, const ColorFilter & shifter,
 		genSpecialPalette(SpecialPalette);
 
 		image->setSpecialPallete(SpecialPalette);
-		image->adjustPalette(shifter);
+		image->adjustPalette(shifter, 8);
 
 		canvas.draw(image, pos.topLeft(), Rect(0, 0, pos.w, pos.h));
 

+ 2 - 0
client/battle/CreatureAnimation.h

@@ -13,6 +13,8 @@
 #include "../widgets/Images.h"
 #include "../gui/CAnimation.h"
 
+#include <SDL_pixels.h>
+
 class CIntObject;
 class CreatureAnimation;
 class Canvas;

+ 39 - 17
client/gui/CAnimation.cpp

@@ -11,16 +11,18 @@
 #include "CAnimation.h"
 
 #include "SDL_Extensions.h"
-#include "SDL_Pixels.h"
 #include "ColorFilter.h"
 
 #include "../CBitmapHandler.h"
 #include "../Graphics.h"
 
-#include "../lib/filesystem/Filesystem.h"
-#include "../lib/filesystem/ISimpleResourceLoader.h"
-#include "../lib/JsonNode.h"
-#include "../lib/CRandomGenerator.h"
+#include "../../lib/filesystem/Filesystem.h"
+#include "../../lib/filesystem/ISimpleResourceLoader.h"
+#include "../../lib/JsonNode.h"
+#include "../../lib/CRandomGenerator.h"
+#include "../../lib/vcmi_endian.h"
+
+#include <SDL_surface.h>
 
 class SDLImageLoader;
 
@@ -96,7 +98,7 @@ public:
 
 	void draw(SDL_Surface * where, int posX=0, int posY=0, const Rect *src=nullptr) const override;
 	void draw(SDL_Surface * where, const Rect * dest, const Rect * src) const override;
-	std::shared_ptr<IImage> scaleFast(float scale) const override;
+	std::shared_ptr<IImage> scaleFast(const Point & size) const override;
 	void exportBitmap(const boost::filesystem::path & path) const override;
 	void playerColored(PlayerColor player) override;
 	void setFlagColor(PlayerColor player) override;
@@ -107,10 +109,12 @@ public:
 	void verticalFlip() override;
 
 	void shiftPalette(int from, int howMany) override;
-	void adjustPalette(const ColorFilter & shifter) override;
+	void adjustPalette(const ColorFilter & shifter, size_t colorsToSkip) override;
 	void resetPalette(int colorID) override;
 	void resetPalette() override;
 
+	void setAlpha(uint8_t value) override;
+
 	void setSpecialPallete(const SpecialPalette & SpecialPalette) override;
 
 	friend class SDLImageLoader;
@@ -142,6 +146,11 @@ std::shared_ptr<IImage> IImage::createFromFile( const std::string & path )
 	return std::shared_ptr<IImage>(new SDLImage(path));
 }
 
+std::shared_ptr<IImage> IImage::createFromSurface( SDL_Surface * source )
+{
+	return std::shared_ptr<IImage>(new SDLImage(source, true));
+}
+
 // Extremely simple file cache. TODO: smarter, more general solution
 class CFileCache
 {
@@ -678,7 +687,11 @@ void SDLImage::draw(SDL_Surface* where, const Rect * dest, const Rect* src) cons
 	if(dest)
 		destShift += dest->topLeft();
 
-	if(surf->format->BitsPerPixel == 8)
+	uint8_t perSurfaceAlpha;
+	if (SDL_GetSurfaceAlphaMod(surf, &perSurfaceAlpha) != 0)
+		logGlobal->error("SDL_GetSurfaceAlphaMod faied! %s", SDL_GetError());
+
+	if(surf->format->BitsPerPixel == 8 && perSurfaceAlpha == SDL_ALPHA_OPAQUE)
 	{
 		CSDL_Ext::blit8bppAlphaTo24bpp(surf, sourceRect, where, destShift);
 	}
@@ -688,9 +701,12 @@ void SDLImage::draw(SDL_Surface* where, const Rect * dest, const Rect* src) cons
 	}
 }
 
-std::shared_ptr<IImage> SDLImage::scaleFast(float scale) const
+std::shared_ptr<IImage> SDLImage::scaleFast(const Point & size) const
 {
-	auto scaled = CSDL_Ext::scaleSurfaceFast(surf, (int)(surf->w * scale), (int)(surf->h * scale));
+	float scaleX = float(size.x) / width();
+	float scaleY = float(size.y) / height();
+
+	auto scaled = CSDL_Ext::scaleSurfaceFast(surf, (int)(surf->w * scaleX), (int)(surf->h * scaleY));
 
 	if (scaled->format && scaled->format->palette) // fix color keying, because SDL loses it at this point
 		CSDL_Ext::setColorKey(scaled, scaled->format->palette->colors[0]);
@@ -701,11 +717,11 @@ std::shared_ptr<IImage> SDLImage::scaleFast(float scale) const
 
 	SDLImage * ret = new SDLImage(scaled, false);
 
-	ret->fullSize.x = (int) round((float)fullSize.x * scale);
-	ret->fullSize.y = (int) round((float)fullSize.y * scale);
+	ret->fullSize.x = (int) round((float)fullSize.x * scaleX);
+	ret->fullSize.y = (int) round((float)fullSize.y * scaleY);
 
-	ret->margins.x = (int) round((float)margins.x * scale);
-	ret->margins.y = (int) round((float)margins.y * scale);
+	ret->margins.x = (int) round((float)margins.x * scaleX);
+	ret->margins.y = (int) round((float)margins.y * scaleY);
 
 	return std::shared_ptr<IImage>(ret);
 }
@@ -720,6 +736,12 @@ void SDLImage::playerColored(PlayerColor player)
 	graphics->blueToPlayersAdv(surf, player);
 }
 
+void SDLImage::setAlpha(uint8_t value)
+{
+	CSDL_Ext::setAlpha (surf, value);
+	SDL_SetSurfaceBlendMode(surf, SDL_BLENDMODE_BLEND);
+}
+
 void SDLImage::setFlagColor(PlayerColor player)
 {
 	if(player < PlayerColor::PLAYER_LIMIT || player==PlayerColor::NEUTRAL)
@@ -786,15 +808,15 @@ void SDLImage::shiftPalette(int from, int howMany)
 	}
 }
 
-void SDLImage::adjustPalette(const ColorFilter & shifter)
+void SDLImage::adjustPalette(const ColorFilter & shifter, size_t colorsToSkip)
 {
 	if(originalPalette == nullptr)
 		return;
 
 	SDL_Palette* palette = surf->format->palette;
 
-	// Note: here we skip the first 8 colors in the palette that predefined in H3Palette
-	for(int i = 8; i < palette->ncolors; i++)
+	// Note: here we skip first colors in the palette that are predefined in H3 images
+	for(int i = colorsToSkip; i < palette->ncolors; i++)
 	{
 		palette->colors[i] = shifter.shiftColor(originalPalette->colors[i]);
 	}

+ 8 - 3
client/gui/CAnimation.h

@@ -9,7 +9,6 @@
  */
 #pragma once
 
-#include "../../lib/vcmi_endian.h"
 #include "../../lib/GameConstants.h"
 
 #ifdef IN
@@ -45,7 +44,7 @@ public:
 	virtual void draw(SDL_Surface * where, int posX = 0, int posY = 0, const Rect * src = nullptr) const = 0;
 	virtual void draw(SDL_Surface * where, const Rect * dest, const Rect * src) const = 0;
 
-	virtual std::shared_ptr<IImage> scaleFast(float scale) const = 0;
+	virtual std::shared_ptr<IImage> scaleFast(const Point & size) const = 0;
 
 	virtual void exportBitmap(const boost::filesystem::path & path) const = 0;
 
@@ -64,10 +63,12 @@ public:
 
 	//only indexed bitmaps, 16 colors maximum
 	virtual void shiftPalette(int from, int howMany) = 0;
-	virtual void adjustPalette(const ColorFilter & shifter) = 0;
+	virtual void adjustPalette(const ColorFilter & shifter, size_t colorsToSkip) = 0;
 	virtual void resetPalette(int colorID) = 0;
 	virtual void resetPalette() = 0;
 
+	virtual void setAlpha(uint8_t value) = 0;
+
 	//only indexed bitmaps with 7 special colors
 	virtual void setSpecialPallete(const SpecialPalette & SpecialPalette) = 0;
 
@@ -79,6 +80,10 @@ public:
 
 	/// loads image from specified file. Returns 0-sized images on failure
 	static std::shared_ptr<IImage> createFromFile( const std::string & path );
+
+	/// temporary compatibility method. Creates IImage from existing SDL_Surface
+	/// Surface will be shared, called must still free it with SDL_FreeSurface
+	static std::shared_ptr<IImage> createFromSurface( SDL_Surface * source );
 };
 
 /// Class for handling animation

+ 8 - 6
client/gui/CGuiHandler.cpp

@@ -11,8 +11,6 @@
 #include "CGuiHandler.h"
 #include "../lib/CondSh.h"
 
-#include <SDL_timer.h>
-
 #include "CIntObject.h"
 #include "CursorHandler.h"
 #include "SDL_Extensions.h"
@@ -24,6 +22,10 @@
 #include "../CPlayerInterface.h"
 #include "../battle/BattleInterface.h"
 
+#include <SDL_render.h>
+#include <SDL_timer.h>
+#include <SDL_events.h>
+
 extern std::queue<SDL_Event> SDLEventsQueue;
 extern boost::mutex eventsM;
 
@@ -641,12 +643,11 @@ const Point & CGuiHandler::getCursorPosition() const
 
 void CGuiHandler::drawFPSCounter()
 {
-	const static SDL_Color yellow = {255, 255, 0, 0};
 	static SDL_Rect overlay = { 0, 0, 64, 32};
-	Uint32 black = SDL_MapRGB(screen->format, 10, 10, 10);
+	uint32_t black = SDL_MapRGB(screen->format, 10, 10, 10);
 	SDL_FillRect(screen, &overlay, black);
 	std::string fps = boost::lexical_cast<std::string>(mainFPSmng->fps);
-	graphics->fonts[FONT_BIG]->renderTextLeft(screen, fps, yellow, Point(10, 10));
+	graphics->fonts[FONT_BIG]->renderTextLeft(screen, fps, Colors::YELLOW, Point(10, 10));
 }
 
 SDL_Keycode CGuiHandler::arrowToNum(SDL_Keycode key)
@@ -751,7 +752,8 @@ void CFramerateManager::framerateDelay()
 	// FPS is higher than it should be, then wait some time
 	if(timeElapsed < rateticks)
 	{
-		SDL_Delay((Uint32)ceil(this->rateticks) - timeElapsed);
+		int timeToSleep = (uint32_t)ceil(this->rateticks) - timeElapsed;
+		boost::this_thread::sleep(boost::posix_time::milliseconds(timeToSleep));
 	}
 
 	currentTicks = SDL_GetTicks();

+ 2 - 2
client/gui/CGuiHandler.h

@@ -10,8 +10,7 @@
 #pragma once
 
 #include "../../lib/Point.h"
-
-#include <SDL_events.h>
+#include "SDL_keycode.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
@@ -20,6 +19,7 @@ template <typename T> struct CondSh;
 VCMI_LIB_NAMESPACE_END
 
 union SDL_Event;
+struct SDL_MouseMotionEvent;
 
 class CFramerateManager;
 class IStatusBar;

+ 2 - 0
client/gui/CIntObject.cpp

@@ -15,6 +15,8 @@
 #include "../CMessage.h"
 
 #include <SDL_pixels.h>
+#include <SDL_surface.h>
+#include <SDL_events.h>
 
 IShowActivatable::IShowActivatable()
 {

+ 2 - 2
client/gui/Canvas.cpp

@@ -76,9 +76,9 @@ void Canvas::draw(Canvas & image, const Point & pos)
 	CSDL_Ext::blitAt(image.surface, renderOffset.x + pos.x, renderOffset.y + pos.y, surface);
 }
 
-void Canvas::drawLine(const Point & from, const Point & dest, const SDL_Color & colorFrom, const SDL_Color & colorDest)
+void Canvas::drawLine(const Point & from, const Point & dest, const ColorRGBA & colorFrom, const ColorRGBA & colorDest)
 {
-	CSDL_Ext::drawLine(surface, renderOffset.x + from.x, renderOffset.y + from.y, renderOffset.x + dest.x, renderOffset.y + dest.y, colorFrom, colorDest);
+	CSDL_Ext::drawLine(surface, renderOffset.x + from.x, renderOffset.y + from.y, renderOffset.x + dest.x, renderOffset.y + dest.y, CSDL_Ext::toSDL(colorFrom), CSDL_Ext::toSDL(colorDest));
 }
 
 void Canvas::drawText(const Point & position, const EFonts & font, const SDL_Color & colorDest, ETextAlignment alignment, const std::string & text )

+ 2 - 1
client/gui/Canvas.h

@@ -11,6 +11,7 @@
 
 #include "TextAlignment.h"
 #include "../../lib/Rect.h"
+#include "../../lib/Color.h"
 
 struct SDL_Color;
 struct SDL_Surface;
@@ -56,7 +57,7 @@ public:
 	void draw(Canvas & image, const Point & pos);
 
 	/// renders continuous, 1-pixel wide line with color gradient
-	void drawLine(const Point & from, const Point & dest, const SDL_Color & colorFrom, const SDL_Color & colorDest);
+	void drawLine(const Point & from, const Point & dest, const ColorRGBA & colorFrom, const ColorRGBA & colorDest);
 
 	/// renders single line of text with specified parameters
 	void drawText(const Point & position, const EFonts & font, const SDL_Color & colorDest, ETextAlignment alignment, const std::string & text );

+ 3 - 0
client/gui/CursorHandler.cpp

@@ -16,6 +16,9 @@
 #include "CAnimation.h"
 #include "../../lib/CConfigHandler.h"
 
+#include <SDL_render.h>
+#include <SDL_events.h>
+
 #ifdef VCMI_APPLE
 #include <dispatch/dispatch.h>
 #endif

+ 10 - 13
client/gui/Fonts.cpp

@@ -12,7 +12,7 @@
 
 #include <SDL_ttf.h>
 
-#include "SDL_Pixels.h"
+#include "SDL_Extensions.h"
 #include "../../lib/JsonNode.h"
 #include "../../lib/vcmi_endian.h"
 #include "../../lib/filesystem/Filesystem.h"
@@ -136,7 +136,7 @@ void CBitmapFont::renderCharacter(SDL_Surface * surface, const BitmapChar & char
 
 	CSDL_Ext::TColorPutter colorPutter = CSDL_Ext::getPutterFor(surface, 0);
 
-	Uint8 bpp = surface->format->BytesPerPixel;
+	uint8_t bpp = surface->format->BytesPerPixel;
 
 	// start of line, may differ from 0 due to end of surface or clipped surface
 	int lineBegin = std::max<int>(0, clipRect.y - posY);
@@ -149,8 +149,8 @@ void CBitmapFont::renderCharacter(SDL_Surface * surface, const BitmapChar & char
 	//for each line in symbol
 	for(int dy = lineBegin; dy <lineEnd; dy++)
 	{
-		Uint8 *dstLine = (Uint8*)surface->pixels;
-		Uint8 *srcLine = character.pixels;
+		uint8_t *dstLine = (uint8_t*)surface->pixels;
+		uint8_t *srcLine = character.pixels;
 
 		// shift source\destination pixels to current position
 		dstLine += (posY+dy) * surface->pitch + posX * bpp;
@@ -159,7 +159,7 @@ void CBitmapFont::renderCharacter(SDL_Surface * surface, const BitmapChar & char
 		//for each column in line
 		for(int dx = rowBegin; dx < rowEnd; dx++)
 		{
-			Uint8* dstPixel = dstLine + dx*bpp;
+			uint8_t* dstPixel = dstLine + dx*bpp;
 			switch(srcLine[dx])
 			{
 			case 1: //black "shadow"
@@ -268,10 +268,7 @@ size_t CTrueTypeFont::getStringWidth(const std::string & data) const
 void CTrueTypeFont::renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const
 {
 	if (color.r != 0 && color.g != 0 && color.b != 0) // not black - add shadow
-	{
-		SDL_Color black = { 0, 0, 0, SDL_ALPHA_OPAQUE};
-		renderText(surface, data, black, pos + Point(1,1));
-	}
+		renderText(surface, data, Colors::BLACK, pos + Point(1,1));
 
 	if (!data.empty())
 	{
@@ -310,7 +307,7 @@ void CBitmapHanFont::renderCharacter(SDL_Surface * surface, int characterIndex,
 	CSDL_Ext::getClipRect(surface, clipRect);
 
 	CSDL_Ext::TColorPutter colorPutter = CSDL_Ext::getPutterFor(surface, 0);
-	Uint8 bpp = surface->format->BytesPerPixel;
+	uint8_t bpp = surface->format->BytesPerPixel;
 
 	// start of line, may differ from 0 due to end of surface or clipped surface
 	int lineBegin = std::max<int>(0, clipRect.y - posY);
@@ -323,8 +320,8 @@ void CBitmapHanFont::renderCharacter(SDL_Surface * surface, int characterIndex,
 	//for each line in symbol
 	for(int dy = lineBegin; dy <lineEnd; dy++)
 	{
-		Uint8 *dstLine = (Uint8*)surface->pixels;
-		Uint8 *source = data.first.get() + getCharacterDataOffset(characterIndex);
+		uint8_t *dstLine = (uint8_t*)surface->pixels;
+		uint8_t *source = data.first.get() + getCharacterDataOffset(characterIndex);
 
 		// shift source\destination pixels to current position
 		dstLine += (posY+dy) * surface->pitch + posX * bpp;
@@ -336,7 +333,7 @@ void CBitmapHanFont::renderCharacter(SDL_Surface * surface, int characterIndex,
 			// select current bit in bitmap
 			int bit = (source[dx / 8] << (dx % 8)) & 0x80;
 
-			Uint8* dstPixel = dstLine + dx*bpp;
+			uint8_t* dstPixel = dstLine + dx*bpp;
 			if (bit != 0)
 				colorPutter(dstPixel, color.r, color.g, color.b);
 		}

+ 0 - 25
client/gui/SDL_Compat.h

@@ -1,25 +0,0 @@
-/*
- * SDL_Compat.h, part of VCMI engine
- *
- * Authors: listed in file AUTHORS in main folder
- *
- * License: GNU General Public License v2.0 or later
- * Full text of license available in license.txt file, in main folder
- *
- */
-#pragma once
- 
-#include <SDL_version.h>
-
-#if (SDL_MAJOR_VERSION == 2)
-
-#include <SDL_keycode.h>
-typedef int SDLX_Coord;
-typedef int SDLX_Size;
-
-
-#else
-#error "unknown or unsupported SDL version"
-#endif
- 
-

+ 54 - 55
client/gui/SDL_Extensions.cpp

@@ -9,7 +9,7 @@
  */
 #include "StdInc.h"
 #include "SDL_Extensions.h"
-#include "SDL_Pixels.h"
+#include "SDL_PixelAccess.h"
 
 #include "../CGameInfo.h"
 #include "../CMessage.h"
@@ -66,6 +66,22 @@ SDL_Rect CSDL_Ext::toSDL(const Rect & rect)
 	return result;
 }
 
+ColorRGBA CSDL_Ext::fromSDL(const SDL_Color & color)
+{
+	return { color.r, color.g, color.b, color.a };
+}
+
+SDL_Color CSDL_Ext::toSDL(const ColorRGBA & color)
+{
+	SDL_Color result;
+	result.r = color.r;
+	result.g = color.g;
+	result.b = color.b;
+	result.a = color.a;
+
+	return result;
+}
+
 void CSDL_Ext::setColors(SDL_Surface *surface, SDL_Color *colors, int firstcolor, int ncolors)
 {
 	SDL_SetPaletteColors(surface->format->palette,colors,firstcolor,ncolors);
@@ -130,12 +146,12 @@ SDL_Surface * CSDL_Ext::copySurface(SDL_Surface * mod) //returns copy of given s
 template<int bpp>
 SDL_Surface * CSDL_Ext::createSurfaceWithBpp(int width, int height)
 {
-	Uint32 rMask = 0, gMask = 0, bMask = 0, aMask = 0;
+	uint32_t rMask = 0, gMask = 0, bMask = 0, aMask = 0;
 
-	Channels::px<bpp>::r.set((Uint8*)&rMask, 255);
-	Channels::px<bpp>::g.set((Uint8*)&gMask, 255);
-	Channels::px<bpp>::b.set((Uint8*)&bMask, 255);
-	Channels::px<bpp>::a.set((Uint8*)&aMask, 255);
+	Channels::px<bpp>::r.set((uint8_t*)&rMask, 255);
+	Channels::px<bpp>::g.set((uint8_t*)&gMask, 255);
+	Channels::px<bpp>::b.set((uint8_t*)&bMask, 255);
+	Channels::px<bpp>::a.set((uint8_t*)&aMask, 255);
 
 	return SDL_CreateRGBSurface(0, width, height, bpp * 8, rMask, gMask, bMask, aMask);
 }
@@ -214,28 +230,28 @@ SDL_Surface * CSDL_Ext::horizontalFlip(SDL_Surface * toRot)
 	return ret;
 }
 
-Uint32 CSDL_Ext::getPixel(SDL_Surface *surface, const int & x, const int & y, bool colorByte)
+uint32_t CSDL_Ext::getPixel(SDL_Surface *surface, const int & x, const int & y, bool colorByte)
 {
 	int bpp = surface->format->BytesPerPixel;
 	/* Here p is the address to the pixel we want to retrieve */
-	Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
+	uint8_t *p = (uint8_t *)surface->pixels + y * surface->pitch + x * bpp;
 
 	switch(bpp)
 	{
 	case 1:
 		if(colorByte)
-			return colorToUint32(surface->format->palette->colors+(*p));
+			return colorTouint32_t(surface->format->palette->colors+(*p));
 		else
 			return *p;
 
 	case 2:
-		return *(Uint16 *)p;
+		return *(uint16_t *)p;
 
 	case 3:
 			return p[0] | p[1] << 8 | p[2] << 16;
 
 	case 4:
-		return *(Uint32 *)p;
+		return *(uint32_t *)p;
 
 	default:
 		return 0;       // shouldn't happen, but avoids warnings
@@ -350,13 +366,13 @@ int CSDL_Ext::blit8bppAlphaTo24bppT(const SDL_Surface * src, const Rect & srcRec
 				return -1; //if we cannot lock the surface
 
 			const SDL_Color *colors = src->format->palette->colors;
-			Uint8 *colory = (Uint8*)src->pixels + srcy*src->pitch + srcx;
-			Uint8 *py = (Uint8*)dst->pixels + dstRect->y*dst->pitch + dstRect->x*bpp;
+			uint8_t *colory = (uint8_t*)src->pixels + srcy*src->pitch + srcx;
+			uint8_t *py = (uint8_t*)dst->pixels + dstRect->y*dst->pitch + dstRect->x*bpp;
 
 			for(int y=h; y; y--, colory+=src->pitch, py+=dst->pitch)
 			{
-				Uint8 *color = colory;
-				Uint8 *p = py;
+				uint8_t *color = colory;
+				uint8_t *p = py;
 
 				for(int x = w; x; x--)
 				{
@@ -383,9 +399,9 @@ int CSDL_Ext::blit8bppAlphaTo24bpp(const SDL_Surface * src, const Rect & srcRect
 	}
 }
 
-Uint32 CSDL_Ext::colorToUint32(const SDL_Color * color)
+uint32_t CSDL_Ext::colorTouint32_t(const SDL_Color * color)
 {
-	Uint32 ret = 0;
+	uint32_t ret = 0;
 	ret+=color->a;
 	ret<<=8; //*=256
 	ret+=color->b;
@@ -416,7 +432,7 @@ static void drawLineX(SDL_Surface * sur, int x1, int y1, int x2, int y2, const S
 		uint8_t b = vstd::lerp(color1.b, color2.b, f);
 		uint8_t a = vstd::lerp(color1.a, color2.a, f);
 
-		Uint8 *p = CSDL_Ext::getPxPtr(sur, x, y);
+		uint8_t *p = CSDL_Ext::getPxPtr(sur, x, y);
 		ColorPutter<4, 0>::PutColor(p, r,g,b,a);
 	}
 }
@@ -433,7 +449,7 @@ static void drawLineY(SDL_Surface * sur, int x1, int y1, int x2, int y2, const S
 		uint8_t b = vstd::lerp(color1.b, color2.b, f);
 		uint8_t a = vstd::lerp(color1.a, color2.a, f);
 
-		Uint8 *p = CSDL_Ext::getPxPtr(sur, x, y);
+		uint8_t *p = CSDL_Ext::getPxPtr(sur, x, y);
 		ColorPutter<4, 0>::PutColor(p, r,g,b,a);
 	}
 }
@@ -445,7 +461,7 @@ void CSDL_Ext::drawLine(SDL_Surface * sur, int x1, int y1, int x2, int y2, const
 
 	if ( width == 0 && height == 0)
 	{
-		Uint8 *p = CSDL_Ext::getPxPtr(sur, x1, y1);
+		uint8_t *p = CSDL_Ext::getPxPtr(sur, x1, y1);
 		ColorPutter<4, 0>::PutColorAlpha(p, color1);
 		return;
 	}
@@ -563,9 +579,9 @@ CSDL_Ext::TColorPutterAlpha CSDL_Ext::getPutterAlphaFor(SDL_Surface * const &des
 #undef CASE_BPP
 }
 
-Uint8 * CSDL_Ext::getPxPtr(const SDL_Surface * const &srf, const int x, const int y)
+uint8_t * CSDL_Ext::getPxPtr(const SDL_Surface * const &srf, const int x, const int y)
 {
-	return (Uint8 *)srf->pixels + y * srf->pitch + x * srf->format->BytesPerPixel;
+	return (uint8_t *)srf->pixels + y * srf->pitch + x * srf->format->BytesPerPixel;
 }
 
 std::string CSDL_Ext::processStr(std::string str, std::vector<std::string> & tor)
@@ -613,9 +629,9 @@ void CSDL_Ext::VflipSurf(SDL_Surface * surf)
 	}
 }
 
-void CSDL_Ext::putPixelWithoutRefresh(SDL_Surface *ekran, const int & x, const int & y, const Uint8 & R, const Uint8 & G, const Uint8 & B, Uint8 A)
+void CSDL_Ext::putPixelWithoutRefresh(SDL_Surface *ekran, const int & x, const int & y, const uint8_t & R, const uint8_t & G, const uint8_t & B, uint8_t A)
 {
-	Uint8 *p = getPxPtr(ekran, x, y);
+	uint8_t *p = getPxPtr(ekran, x, y);
 	getPutterFor(ekran, false)(p, R, G, B);
 
 	switch(ekran->format->BytesPerPixel)
@@ -626,7 +642,7 @@ void CSDL_Ext::putPixelWithoutRefresh(SDL_Surface *ekran, const int & x, const i
 	}
 }
 
-void CSDL_Ext::putPixelWithoutRefreshIfInSurf(SDL_Surface *ekran, const int & x, const int & y, const Uint8 & R, const Uint8 & G, const Uint8 & B, Uint8 A)
+void CSDL_Ext::putPixelWithoutRefreshIfInSurf(SDL_Surface *ekran, const int & x, const int & y, const uint8_t & R, const uint8_t & G, const uint8_t & B, uint8_t A)
 {
 	const SDL_Rect & rect = ekran->clip_rect;
 
@@ -649,7 +665,7 @@ void CSDL_Ext::applyEffectBpp(SDL_Surface * surf, const Rect & rect, int mode )
 			{
 				for(int yp = rect.y; yp < rect.y + rect.h; ++yp)
 				{
-					Uint8 * pixel = (ui8*)surf->pixels + yp * surf->pitch + xp * surf->format->BytesPerPixel;
+					uint8_t * pixel = (ui8*)surf->pixels + yp * surf->pitch + xp * surf->format->BytesPerPixel;
 					int r = Channels::px<bpp>::r.get(pixel);
 					int g = Channels::px<bpp>::g.get(pixel);
 					int b = Channels::px<bpp>::b.get(pixel);
@@ -682,7 +698,7 @@ void CSDL_Ext::applyEffectBpp(SDL_Surface * surf, const Rect & rect, int mode )
 			{
 				for(int yp = rect.y; yp < rect.y + rect.h; ++yp)
 				{
-					Uint8 * pixel = (ui8*)surf->pixels + yp * surf->pitch + xp * surf->format->BytesPerPixel;
+					uint8_t * pixel = (ui8*)surf->pixels + yp * surf->pitch + xp * surf->format->BytesPerPixel;
 
 					int r = Channels::px<bpp>::r.get(pixel);
 					int g = Channels::px<bpp>::g.get(pixel);
@@ -728,8 +744,8 @@ void scaleSurfaceFastInternal(SDL_Surface *surf, SDL_Surface *ret)
 				origY = static_cast<int>(floor(factorY * y));
 
 			// Get pointers to source pixels
-			Uint8 *srcPtr = (Uint8*)surf->pixels + origY * surf->pitch + origX * bpp;
-			Uint8 *destPtr = (Uint8*)ret->pixels + y * ret->pitch + x * bpp;
+			uint8_t *srcPtr = (uint8_t*)surf->pixels + origY * surf->pitch + origX * bpp;
+			uint8_t *destPtr = (uint8_t*)ret->pixels + y * ret->pitch + x * bpp;
 
 			memcpy(destPtr, srcPtr, bpp);
 		}
@@ -783,10 +799,10 @@ void scaleSurfaceInternal(SDL_Surface *surf, SDL_Surface *ret)
 			//assert( w11 + w12 + w21 + w22 > 0.99 && w11 + w12 + w21 + w22 < 1.01);//total weight is ~1.0
 
 			// Get pointers to source pixels
-			Uint8 *p11 = (Uint8*)surf->pixels + int(y1) * surf->pitch + int(x1) * bpp;
-			Uint8 *p12 = p11 + bpp;
-			Uint8 *p21 = p11 + surf->pitch;
-			Uint8 *p22 = p21 + bpp;
+			uint8_t *p11 = (uint8_t*)surf->pixels + int(y1) * surf->pitch + int(x1) * bpp;
+			uint8_t *p12 = p11 + bpp;
+			uint8_t *p21 = p11 + surf->pitch;
+			uint8_t *p22 = p21 + bpp;
 			// Calculate resulting channels
 #define PX(X, PTR) Channels::px<bpp>::X.get(PTR)
 			int resR = static_cast<int>(PX(r, p11) * w11 + PX(r, p12) * w12 + PX(r, p21) * w21 + PX(r, p22) * w22);
@@ -795,7 +811,7 @@ void scaleSurfaceInternal(SDL_Surface *surf, SDL_Surface *ret)
 			int resA = static_cast<int>(PX(a, p11) * w11 + PX(a, p12) * w12 + PX(a, p21) * w21 + PX(a, p22) * w22);
 			//assert(resR < 256 && resG < 256 && resB < 256 && resA < 256);
 #undef PX
-			Uint8 *dest = (Uint8*)ret->pixels + y * ret->pitch + x * bpp;
+			uint8_t *dest = (uint8_t*)ret->pixels + y * ret->pitch + x * bpp;
 			Channels::px<bpp>::r.set(dest, resR);
 			Channels::px<bpp>::g.set(dest, resG);
 			Channels::px<bpp>::b.set(dest, resB);
@@ -836,7 +852,10 @@ void CSDL_Ext::blitSurface(SDL_Surface * src, const Rect & srcRectInput, SDL_Sur
 	SDL_Rect srcRect = CSDL_Ext::toSDL(srcRectInput);
 	SDL_Rect dstRect = CSDL_Ext::toSDL(Rect(dstPoint, srcRectInput.dimensions()));
 
-	SDL_UpperBlit(src, &srcRect, dst, &dstRect);
+	int result = SDL_UpperBlit(src, &srcRect, dst, &dstRect);
+
+	if (result != 0)
+		logGlobal->error("SDL_UpperBlit failed! %s", SDL_GetError());
 }
 
 void CSDL_Ext::blitSurface(SDL_Surface * src, SDL_Surface * dst, const Point & dest)
@@ -861,26 +880,6 @@ void CSDL_Ext::fillRect( SDL_Surface *dst, const Rect & dstrect, const SDL_Color
 	SDL_FillRect(dst, &newRect, sdlColor);
 }
 
-void CSDL_Ext::fillTexture(SDL_Surface *dst, SDL_Surface * src)
-{
-	SDL_Rect srcRect;
-	SDL_Rect dstRect;
-
-	SDL_GetClipRect(src, &srcRect);
-	SDL_GetClipRect(dst, &dstRect);
-
-	for (int y=dstRect.y; y < dstRect.y + dstRect.h; y+=srcRect.h)
-	{
-		for (int x=dstRect.x; x < dstRect.x + dstRect.w; x+=srcRect.w)
-		{
-			int xLeft = std::min<int>(srcRect.w, dstRect.x + dstRect.w - x);
-			int yLeft = std::min<int>(srcRect.h, dstRect.y + dstRect.h - y);
-			SDL_Rect currentDest{x, y, xLeft, yLeft};
-			SDL_BlitSurface(src, &srcRect, dst, &currentDest);
-		}
-	}
-}
-
 SDL_Color CSDL_Ext::makeColor(ui8 r, ui8 g, ui8 b, ui8 a)
 {
 	SDL_Color ret = {r, g, b, a};

+ 15 - 11
client/gui/SDL_Extensions.h

@@ -9,11 +9,11 @@
  */
 
 #pragma once
-#include <SDL_render.h>
-#include <SDL_events.h>
 #include "../../lib/GameConstants.h"
 #include "../../lib/Rect.h"
+#include "../../lib/Color.h"
 
+struct SDL_Rect;
 struct SDL_Window;
 struct SDL_Renderer;
 struct SDL_Texture;
@@ -79,6 +79,12 @@ Rect fromSDL(const SDL_Rect & rect);
 /// creates SDL_Rect using provided rect
 SDL_Rect toSDL(const Rect & rect);
 
+/// creates Color using provided SDL_Color
+ColorRGBA fromSDL(const SDL_Color & color);
+
+/// creates SDL_Color using provided Color
+SDL_Color toSDL(const ColorRGBA & color);
+
 void setColors(SDL_Surface *surface, SDL_Color *colors, int firstcolor, int ncolors);
 void warpMouse(int x, int y);
 bool isCtrlKeyDown();
@@ -108,8 +114,8 @@ std::string makeNumberShort(IntType number, IntType maxLength = 3) //the output
 
 Rect genRect(const int & hh, const int & ww, const int & xx, const int & yy);
 
-typedef void (*TColorPutter)(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B);
-typedef void (*TColorPutterAlpha)(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B, const Uint8 & A);
+typedef void (*TColorPutter)(uint8_t *&ptr, const uint8_t & R, const uint8_t & G, const uint8_t & B);
+typedef void (*TColorPutterAlpha)(uint8_t *&ptr, const uint8_t & R, const uint8_t & G, const uint8_t & B, const uint8_t & A);
 
 	void blitAt(SDL_Surface * src, int x, int y, SDL_Surface * dst=screen);
 	void blitAt(SDL_Surface * src, const Rect & pos, SDL_Surface * dst=screen);
@@ -122,28 +128,26 @@ typedef void (*TColorPutterAlpha)(Uint8 *&ptr, const Uint8 & R, const Uint8 & G,
 
 	void fillSurface(SDL_Surface *dst, const SDL_Color & color);
 	void fillRect(SDL_Surface *dst, const Rect & dstrect, const SDL_Color & color);
-	//fill dest image with source texture.
-	void fillTexture(SDL_Surface *dst, SDL_Surface * sourceTexture);
 
 	void updateRect(SDL_Surface *surface, const Rect & rect);
 
-	void putPixelWithoutRefresh(SDL_Surface *ekran, const int & x, const int & y, const Uint8 & R, const Uint8 & G, const Uint8 & B, Uint8 A = 255);
-	void putPixelWithoutRefreshIfInSurf(SDL_Surface *ekran, const int & x, const int & y, const Uint8 & R, const Uint8 & G, const Uint8 & B, Uint8 A = 255);
+	void putPixelWithoutRefresh(SDL_Surface *ekran, const int & x, const int & y, const uint8_t & R, const uint8_t & G, const uint8_t & B, uint8_t A = 255);
+	void putPixelWithoutRefreshIfInSurf(SDL_Surface *ekran, const int & x, const int & y, const uint8_t & R, const uint8_t & G, const uint8_t & B, uint8_t A = 255);
 
 	SDL_Surface * verticalFlip(SDL_Surface * toRot); //vertical flip
 	SDL_Surface * horizontalFlip(SDL_Surface * toRot); //horizontal flip
-	Uint32 getPixel(SDL_Surface *surface, const int & x, const int & y, bool colorByte = false);
+	uint32_t getPixel(SDL_Surface *surface, const int & x, const int & y, bool colorByte = false);
 	bool isTransparent(SDL_Surface * srf, int x, int y); //checks if surface is transparent at given position
 	bool isTransparent(SDL_Surface * srf, const Point &  position); //checks if surface is transparent at given position
 
-	Uint8 *getPxPtr(const SDL_Surface * const &srf, const int x, const int y);
+	uint8_t *getPxPtr(const SDL_Surface * const &srf, const int x, const int y);
 	TColorPutter getPutterFor(SDL_Surface  * const &dest, int incrementing); //incrementing: -1, 0, 1
 	TColorPutterAlpha getPutterAlphaFor(SDL_Surface  * const &dest, int incrementing); //incrementing: -1, 0, 1
 
 	template<int bpp>
 	int blit8bppAlphaTo24bppT(const SDL_Surface * src, const Rect & srcRect, SDL_Surface * dst, const Point & dstPoint); //blits 8 bpp surface with alpha channel to 24 bpp surface
 	int blit8bppAlphaTo24bpp(const SDL_Surface * src, const Rect & srcRect, SDL_Surface * dst, const Point & dstPoint); //blits 8 bpp surface with alpha channel to 24 bpp surface
-	Uint32 colorToUint32(const SDL_Color * color); //little endian only
+	uint32_t colorTouint32_t(const SDL_Color * color); //little endian only
 	SDL_Color makeColor(ui8 r, ui8 g, ui8 b, ui8 a);
 
 	void update(SDL_Surface * what = screen); //updates whole surface (default - main screen)

+ 48 - 47
client/gui/SDL_Pixels.h → client/gui/SDL_PixelAccess.h

@@ -1,5 +1,5 @@
 /*
- * SDL_Pixels.h, part of VCMI engine
+ * SDL_PixelAccess.h, part of VCMI engine
  *
  * Authors: listed in file AUTHORS in main folder
  *
@@ -12,6 +12,7 @@
 #include "SDL_Extensions.h"
 
 #include <SDL_endian.h>
+#include <SDL_pixels.h>
 
 // for accessing channels from pixel in format-independent way
 //should be as fast as accessing via pointer at least for 3-4 bytes per pixel
@@ -20,20 +21,20 @@ namespace Channels
 	// channel not present in this format
 	struct channel_empty
 	{
-		static STRONG_INLINE void set(Uint8*, Uint8) {}
-		static STRONG_INLINE Uint8 get(const Uint8 *) { return 255;}
+		static STRONG_INLINE void set(uint8_t*, uint8_t) {}
+		static STRONG_INLINE uint8_t get(const uint8_t *) { return 255;}
 	};
 
 	// channel which uses whole pixel
 	template<int offset>
 	struct channel_pixel
 	{
-		static STRONG_INLINE void set(Uint8 *ptr, Uint8 value)
+		static STRONG_INLINE void set(uint8_t *ptr, uint8_t value)
 		{
 			ptr[offset] = value;
 		}
 
-		static STRONG_INLINE Uint8 get(const Uint8 *ptr)
+		static STRONG_INLINE uint8_t get(const uint8_t *ptr)
 		{
 			return ptr[offset];
 		}
@@ -44,16 +45,16 @@ namespace Channels
 	struct channel_subpx
 	{
 
-		static void STRONG_INLINE set(Uint8 *ptr, Uint8 value)
+		static void STRONG_INLINE set(uint8_t *ptr, uint8_t value)
 		{
-			Uint16 * const pixel = (Uint16*)ptr;
-			Uint8 subpx = value >> (8 - bits);
+			uint16_t * const pixel = (uint16_t*)ptr;
+			uint8_t subpx = value >> (8 - bits);
 			*pixel = (*pixel & ~mask) | ((subpx << shift) & mask );
 		}
 
-		static Uint8 STRONG_INLINE get(const Uint8 *ptr)
+		static uint8_t STRONG_INLINE get(const uint8_t *ptr)
 		{
-			Uint8 subpx = (*((Uint16 *)ptr) & mask) >> shift;
+			uint8_t subpx = (*((uint16_t *)ptr) & mask) >> shift;
 			return (subpx << (8 - bits)) | (subpx >> (2*bits - 8));
 		}
 	};
@@ -122,39 +123,39 @@ namespace Channels
 template<int bpp, int incrementPtr>
 struct ColorPutter
 {
-	static STRONG_INLINE void PutColor(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B);
-	static STRONG_INLINE void PutColor(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B, const Uint8 & A);
-	static STRONG_INLINE void PutColorAlphaSwitch(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B, const Uint8 & A);
-	static STRONG_INLINE void PutColor(Uint8 *&ptr, const SDL_Color & Color);
-	static STRONG_INLINE void PutColorAlpha(Uint8 *&ptr, const SDL_Color & Color);
-	static STRONG_INLINE void PutColorRow(Uint8 *&ptr, const SDL_Color & Color, size_t count);
+	static STRONG_INLINE void PutColor(uint8_t *&ptr, const uint8_t & R, const uint8_t & G, const uint8_t & B);
+	static STRONG_INLINE void PutColor(uint8_t *&ptr, const uint8_t & R, const uint8_t & G, const uint8_t & B, const uint8_t & A);
+	static STRONG_INLINE void PutColorAlphaSwitch(uint8_t *&ptr, const uint8_t & R, const uint8_t & G, const uint8_t & B, const uint8_t & A);
+	static STRONG_INLINE void PutColor(uint8_t *&ptr, const SDL_Color & Color);
+	static STRONG_INLINE void PutColorAlpha(uint8_t *&ptr, const SDL_Color & Color);
+	static STRONG_INLINE void PutColorRow(uint8_t *&ptr, const SDL_Color & Color, size_t count);
 };
 
 template <int incrementPtr>
 struct ColorPutter<2, incrementPtr>
 {
-	static STRONG_INLINE void PutColor(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B);
-	static STRONG_INLINE void PutColor(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B, const Uint8 & A);
-	static STRONG_INLINE void PutColorAlphaSwitch(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B, const Uint8 & A);
-	static STRONG_INLINE void PutColor(Uint8 *&ptr, const SDL_Color & Color);
-	static STRONG_INLINE void PutColorAlpha(Uint8 *&ptr, const SDL_Color & Color);
-	static STRONG_INLINE void PutColorRow(Uint8 *&ptr, const SDL_Color & Color, size_t count);
+	static STRONG_INLINE void PutColor(uint8_t *&ptr, const uint8_t & R, const uint8_t & G, const uint8_t & B);
+	static STRONG_INLINE void PutColor(uint8_t *&ptr, const uint8_t & R, const uint8_t & G, const uint8_t & B, const uint8_t & A);
+	static STRONG_INLINE void PutColorAlphaSwitch(uint8_t *&ptr, const uint8_t & R, const uint8_t & G, const uint8_t & B, const uint8_t & A);
+	static STRONG_INLINE void PutColor(uint8_t *&ptr, const SDL_Color & Color);
+	static STRONG_INLINE void PutColorAlpha(uint8_t *&ptr, const SDL_Color & Color);
+	static STRONG_INLINE void PutColorRow(uint8_t *&ptr, const SDL_Color & Color, size_t count);
 };
 
 template<int bpp, int incrementPtr>
-STRONG_INLINE void ColorPutter<bpp, incrementPtr>::PutColorAlpha(Uint8 *&ptr, const SDL_Color & Color)
+STRONG_INLINE void ColorPutter<bpp, incrementPtr>::PutColorAlpha(uint8_t *&ptr, const SDL_Color & Color)
 {
 	PutColor(ptr, Color.r, Color.g, Color.b, Color.a);
 }
 
 template<int bpp, int incrementPtr>
-STRONG_INLINE void ColorPutter<bpp, incrementPtr>::PutColor(Uint8 *&ptr, const SDL_Color & Color)
+STRONG_INLINE void ColorPutter<bpp, incrementPtr>::PutColor(uint8_t *&ptr, const SDL_Color & Color)
 {
 	PutColor(ptr, Color.r, Color.g, Color.b);
 }
 
 template<int bpp, int incrementPtr>
-STRONG_INLINE void ColorPutter<bpp, incrementPtr>::PutColorAlphaSwitch(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B, const Uint8 & A)
+STRONG_INLINE void ColorPutter<bpp, incrementPtr>::PutColorAlphaSwitch(uint8_t *&ptr, const uint8_t & R, const uint8_t & G, const uint8_t & B, const uint8_t & A)
 {
 	switch (A)
 	{
@@ -166,9 +167,9 @@ STRONG_INLINE void ColorPutter<bpp, incrementPtr>::PutColorAlphaSwitch(Uint8 *&p
 		return;
 	case 128:  // optimized
 		PutColor(ptr,
-				 ((Uint16)R + Channels::px<bpp>::r.get(ptr)) >> 1,
-				 ((Uint16)G + Channels::px<bpp>::g.get(ptr)) >> 1,
-				 ((Uint16)B + Channels::px<bpp>::b.get(ptr)) >> 1);
+				 ((uint16_t)R + Channels::px<bpp>::r.get(ptr)) >> 1,
+				 ((uint16_t)G + Channels::px<bpp>::g.get(ptr)) >> 1,
+				 ((uint16_t)B + Channels::px<bpp>::b.get(ptr)) >> 1);
 		return;
 	default:
 		PutColor(ptr, R, G, B, A);
@@ -177,16 +178,16 @@ STRONG_INLINE void ColorPutter<bpp, incrementPtr>::PutColorAlphaSwitch(Uint8 *&p
 }
 
 template<int bpp, int incrementPtr>
-STRONG_INLINE void ColorPutter<bpp, incrementPtr>::PutColor(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B, const Uint8 & A)
+STRONG_INLINE void ColorPutter<bpp, incrementPtr>::PutColor(uint8_t *&ptr, const uint8_t & R, const uint8_t & G, const uint8_t & B, const uint8_t & A)
 {
-	PutColor(ptr, ((((Uint32)R - (Uint32)Channels::px<bpp>::r.get(ptr))*(Uint32)A) >> 8 ) + (Uint32)Channels::px<bpp>::r.get(ptr),
-				  ((((Uint32)G - (Uint32)Channels::px<bpp>::g.get(ptr))*(Uint32)A) >> 8 ) + (Uint32)Channels::px<bpp>::g.get(ptr),
-				  ((((Uint32)B - (Uint32)Channels::px<bpp>::b.get(ptr))*(Uint32)A) >> 8 ) + (Uint32)Channels::px<bpp>::b.get(ptr));
+	PutColor(ptr, ((((uint32_t)R - (uint32_t)Channels::px<bpp>::r.get(ptr))*(uint32_t)A) >> 8 ) + (uint32_t)Channels::px<bpp>::r.get(ptr),
+				  ((((uint32_t)G - (uint32_t)Channels::px<bpp>::g.get(ptr))*(uint32_t)A) >> 8 ) + (uint32_t)Channels::px<bpp>::g.get(ptr),
+				  ((((uint32_t)B - (uint32_t)Channels::px<bpp>::b.get(ptr))*(uint32_t)A) >> 8 ) + (uint32_t)Channels::px<bpp>::b.get(ptr));
 }
 
 
 template<int bpp, int incrementPtr>
-STRONG_INLINE void ColorPutter<bpp, incrementPtr>::PutColor(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B)
+STRONG_INLINE void ColorPutter<bpp, incrementPtr>::PutColor(uint8_t *&ptr, const uint8_t & R, const uint8_t & G, const uint8_t & B)
 {
 	static_assert(incrementPtr >= -1 && incrementPtr <= +1, "Invalid incrementPtr value!");
 
@@ -204,11 +205,11 @@ STRONG_INLINE void ColorPutter<bpp, incrementPtr>::PutColor(Uint8 *&ptr, const U
 }
 
 template<int bpp, int incrementPtr>
-STRONG_INLINE void ColorPutter<bpp, incrementPtr>::PutColorRow(Uint8 *&ptr, const SDL_Color & Color, size_t count)
+STRONG_INLINE void ColorPutter<bpp, incrementPtr>::PutColorRow(uint8_t *&ptr, const SDL_Color & Color, size_t count)
 {
 	if (count)
 	{
-		Uint8 *pixel = ptr;
+		uint8_t *pixel = ptr;
 		PutColor(ptr, Color.r, Color.g, Color.b);
 
 		for (size_t i=0; i<count-1; i++)
@@ -220,12 +221,12 @@ STRONG_INLINE void ColorPutter<bpp, incrementPtr>::PutColorRow(Uint8 *&ptr, cons
 }
 
 template <int incrementPtr>
-STRONG_INLINE void ColorPutter<2, incrementPtr>::PutColor(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B)
+STRONG_INLINE void ColorPutter<2, incrementPtr>::PutColor(uint8_t *&ptr, const uint8_t & R, const uint8_t & G, const uint8_t & B)
 {
 	if(incrementPtr == -1)
 		ptr -= 2;
 
-	Uint16 * const px = (Uint16*)ptr;
+	uint16_t * const px = (uint16_t*)ptr;
 	*px = (B>>3) + ((G>>2) << 5) + ((R>>3) << 11); //drop least significant bits of 24 bpp encoded color
 
 	if(incrementPtr == 1)
@@ -233,7 +234,7 @@ STRONG_INLINE void ColorPutter<2, incrementPtr>::PutColor(Uint8 *&ptr, const Uin
 }
 
 template <int incrementPtr>
-STRONG_INLINE void ColorPutter<2, incrementPtr>::PutColorAlphaSwitch(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B, const Uint8 & A)
+STRONG_INLINE void ColorPutter<2, incrementPtr>::PutColorAlphaSwitch(uint8_t *&ptr, const uint8_t & R, const uint8_t & G, const uint8_t & B, const uint8_t & A)
 {
 	switch (A)
 	{
@@ -250,17 +251,17 @@ STRONG_INLINE void ColorPutter<2, incrementPtr>::PutColorAlphaSwitch(Uint8 *&ptr
 }
 
 template <int incrementPtr>
-STRONG_INLINE void ColorPutter<2, incrementPtr>::PutColor(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B, const Uint8 & A)
+STRONG_INLINE void ColorPutter<2, incrementPtr>::PutColor(uint8_t *&ptr, const uint8_t & R, const uint8_t & G, const uint8_t & B, const uint8_t & A)
 {
 	const int rbit = 5, gbit = 6, bbit = 5; //bits per color
 	const int rmask = 0xF800, gmask = 0x7E0, bmask = 0x1F;
 	const int rshift = 11, gshift = 5, bshift = 0;
 
-	const Uint8 r5 = (*((Uint16 *)ptr) & rmask) >> rshift,
-		b5 = (*((Uint16 *)ptr) & bmask) >> bshift,
-		g5 = (*((Uint16 *)ptr) & gmask) >> gshift;
+	const uint8_t r5 = (*((uint16_t *)ptr) & rmask) >> rshift,
+		b5 = (*((uint16_t *)ptr) & bmask) >> bshift,
+		g5 = (*((uint16_t *)ptr) & gmask) >> gshift;
 
-	const Uint32 r8 = (r5 << (8 - rbit)) | (r5 >> (2*rbit - 8)),
+	const uint32_t r8 = (r5 << (8 - rbit)) | (r5 >> (2*rbit - 8)),
 		g8 = (g5 << (8 - gbit)) | (g5 >> (2*gbit - 8)),
 		b8 = (b5 << (8 - bbit)) | (b5 >> (2*bbit - 8));
 
@@ -271,22 +272,22 @@ STRONG_INLINE void ColorPutter<2, incrementPtr>::PutColor(Uint8 *&ptr, const Uin
 }
 
 template <int incrementPtr>
-STRONG_INLINE void ColorPutter<2, incrementPtr>::PutColorAlpha(Uint8 *&ptr, const SDL_Color & Color)
+STRONG_INLINE void ColorPutter<2, incrementPtr>::PutColorAlpha(uint8_t *&ptr, const SDL_Color & Color)
 {
 	PutColor(ptr, Color.r, Color.g, Color.b, Color.a);
 }
 
 template <int incrementPtr>
-STRONG_INLINE void ColorPutter<2, incrementPtr>::PutColor(Uint8 *&ptr, const SDL_Color & Color)
+STRONG_INLINE void ColorPutter<2, incrementPtr>::PutColor(uint8_t *&ptr, const SDL_Color & Color)
 {
 	PutColor(ptr, Color.r, Color.g, Color.b);
 }
 
 template <int incrementPtr>
-STRONG_INLINE void ColorPutter<2, incrementPtr>::PutColorRow(Uint8 *&ptr, const SDL_Color & Color, size_t count)
+STRONG_INLINE void ColorPutter<2, incrementPtr>::PutColorRow(uint8_t *&ptr, const SDL_Color & Color, size_t count)
 {
 	//drop least significant bits of 24 bpp encoded color
-	Uint16 pixel = (Color.b>>3) + ((Color.g>>2) << 5) + ((Color.r>>3) << 11);
+	uint16_t pixel = (Color.b>>3) + ((Color.g>>2) << 5) + ((Color.r>>3) << 11);
 
 	for (size_t i=0; i<count; i++)
 	{

+ 4 - 4
client/lobby/CBonusSelection.cpp

@@ -492,8 +492,8 @@ CBonusSelection::CRegion::CRegion(int id, bool accessible, bool selectable, cons
 	graphicsSelected->disable();
 	graphicsStriped = std::make_shared<CPicture>(prefix + "Co" + suffix + ".BMP");
 	graphicsStriped->disable();
-	pos.w = graphicsNotSelected->bg->w;
-	pos.h = graphicsNotSelected->bg->h;
+	pos.w = graphicsNotSelected->pos.w;
+	pos.h = graphicsNotSelected->pos.h;
 
 }
 
@@ -525,7 +525,7 @@ void CBonusSelection::CRegion::clickLeft(tribool down, bool previousState)
 	if(indeterminate(down))
 		return;
 
-	if(!down && selectable && !CSDL_Ext::isTransparent(graphicsNotSelected->getSurface(), GH.getCursorPosition() - pos.topLeft()))
+	if(!down && selectable && !graphicsNotSelected->getSurface()->isTransparent(GH.getCursorPosition() - pos.topLeft()))
 	{
 		CSH->setCampaignMap(idOfMapAndRegion);
 	}
@@ -535,7 +535,7 @@ void CBonusSelection::CRegion::clickRight(tribool down, bool previousState)
 {
 	// FIXME: For some reason "down" is only ever contain indeterminate_value
 	auto text = CSH->si->campState->camp->scenarios[idOfMapAndRegion].regionText;
-	if(!CSDL_Ext::isTransparent(graphicsNotSelected->getSurface(), GH.getCursorPosition() - pos.topLeft()) && text.size())
+	if(!graphicsNotSelected->getSurface()->isTransparent(GH.getCursorPosition() - pos.topLeft()) && text.size())
 	{
 		CRClickPopup::createAndPush(text);
 	}

+ 3 - 1
client/lobby/CSelectionBase.cpp

@@ -44,6 +44,8 @@
 #include "../../lib/mapping/CMapInfo.h"
 #include "../../lib/serializer/Connection.h"
 
+#include <SDL_events.h>
+
 ISelectionScreenInfo::ISelectionScreenInfo(ESelectionScreen ScreenType)
 	: screenType(ScreenType)
 {
@@ -312,7 +314,7 @@ CChatBox::CChatBox(const Rect & rect)
 	type |= REDRAW_PARENT;
 
 	const int height = static_cast<int>(graphics->fonts[FONT_SMALL]->getLineHeight());
-	inputBox = std::make_shared<CTextInput>(Rect(0, rect.h - height, rect.w, height));
+	inputBox = std::make_shared<CTextInput>(Rect(0, rect.h - height, rect.w, height), EFonts::FONT_SMALL, 0);
 	inputBox->removeUsedEvents(KEYBOARD);
 	chatHistory = std::make_shared<CTextBox>("", Rect(0, 0, rect.w, rect.h - height), 1);
 

+ 1 - 0
client/lobby/SelectionTab.cpp

@@ -36,6 +36,7 @@
 #include "../../lib/mapping/CMapInfo.h"
 #include "../../lib/serializer/Connection.h"
 
+#include <SDL_events.h>
 
 bool mapSorter::operator()(const std::shared_ptr<CMapInfo> aaa, const std::shared_ptr<CMapInfo> bbb)
 {

+ 1 - 4
client/mainmenu/CMainMenu.cpp

@@ -56,6 +56,7 @@
 #include "../../lib/CondSh.h"
 #include "../../lib/mapping/CCampaignHandler.h"
 
+#include <SDL_events.h>
 
 namespace fs = boost::filesystem;
 
@@ -76,11 +77,7 @@ CMenuScreen::CMenuScreen(const JsonNode & configNode)
 
 	background = std::make_shared<CPicture>(config["background"].String());
 	if(config["scalable"].Bool())
-	{
-		if(background->bg->format->palette)
-			background->convertToScreenBPP();
 		background->scaleTo(Point(screen->w, screen->h));
-	}
 
 	pos = background->center();
 

+ 7 - 7
client/mapHandler.cpp

@@ -899,22 +899,22 @@ void CMapHandler::CMapBlitter::blit(SDL_Surface * targetSurf, const MapDrawingIn
 				{
 					if(parent->map->getTile(int3(pos.x, pos.y, pos.z)).blocked) //temporary hiding blocked positions
 					{
-						static SDL_Surface * block = nullptr;
+						static std::shared_ptr<IImage> block;
 						if (!block)
-							block = BitmapHandler::loadBitmap("blocked");
+							block = IImage::createFromFile("blocked");
 
-						CSDL_Ext::blitSurface(block, targetSurf, realTileRect.topLeft());
+						block->draw(targetSurf, realTileRect.x, realTileRect.y);
 					}
 				}
 				if (settings["session"]["showVisit"].Bool())
 				{
 					if(parent->map->getTile(int3(pos.x, pos.y, pos.z)).visitable) //temporary hiding visitable positions
 					{
-						static SDL_Surface * visit = nullptr;
+						static std::shared_ptr<IImage> visit;
 						if (!visit)
-							visit = BitmapHandler::loadBitmap("visitable");
+							visit = IImage::createFromFile("visitable");
 
-						CSDL_Ext::blitSurface(visit, targetSurf, realTileRect.topLeft());
+						visit->draw(targetSurf, realTileRect.x, realTileRect.y);
 					}
 				}
 			}
@@ -1434,7 +1434,7 @@ std::shared_ptr<IImage> CMapHandler::CMapCache::requestWorldViewCacheOrCreate(CM
 	auto iter = cache.find(key);
 	if(iter == cache.end())
 	{
-		auto scaled = fullSurface->scaleFast(worldViewCachedScale);
+		auto scaled = fullSurface->scaleFast(fullSurface->dimensions() * worldViewCachedScale);
 		cache[key] = scaled;
 		return scaled;
 	}

+ 24 - 40
client/widgets/AdventureMapClasses.cpp

@@ -22,7 +22,8 @@
 #include "../mainmenu/CMainMenu.h"
 
 #include "../gui/CGuiHandler.h"
-#include "../gui/SDL_Pixels.h"
+#include "../gui/SDL_PixelAccess.h"
+#include "../gui/CAnimation.h"
 
 #include "../windows/InfoWindows.h"
 #include "../windows/CAdvmapInterface.h"
@@ -42,6 +43,10 @@
 #include "../../lib/mapping/CMap.h"
 #include "ClientCommandManager.h"
 
+#include <SDL_surface.h>
+#include <SDL_keyboard.h>
+#include <SDL_events.h>
+
 CList::CListItem::CListItem(CList * Parent)
 	: CIntObject(LCLICK | RCLICK | HOVER),
 	parent(Parent),
@@ -182,11 +187,11 @@ CHeroList::CEmptyHeroItem::CEmptyHeroItem()
 {
 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 	movement = std::make_shared<CAnimImage>("IMOBIL", 0, 0, 0, 1);
-	portrait = std::make_shared<CPicture>("HPSXXX", movement->pos.w + 1);
+	portrait = std::make_shared<CPicture>("HPSXXX", movement->pos.w + 1, 0);
 	mana = std::make_shared<CAnimImage>("IMANA", 0, 0, movement->pos.w + portrait->pos.w + 2, 1 );
 
 	pos.w = mana->pos.w + mana->pos.x - pos.x;
-	pos.h = std::max(std::max<SDLX_Size>(movement->pos.h + 1, mana->pos.h + 1), portrait->pos.h);
+	pos.h = std::max(std::max<int>(movement->pos.h + 1, mana->pos.h + 1), portrait->pos.h);
 }
 
 CHeroList::CHeroItem::CHeroItem(CHeroList *parent, const CGHeroInstance * Hero)
@@ -199,7 +204,7 @@ CHeroList::CHeroItem::CHeroItem(CHeroList *parent, const CGHeroInstance * Hero)
 	mana = std::make_shared<CAnimImage>("IMANA", 0, 0, movement->pos.w + portrait->pos.w + 2, 1);
 
 	pos.w = mana->pos.w + mana->pos.x - pos.x;
-	pos.h = std::max(std::max<SDLX_Size>(movement->pos.h + 1, mana->pos.h + 1), portrait->pos.h);
+	pos.h = std::max(std::max<int>(movement->pos.h + 1, mana->pos.h + 1), portrait->pos.h);
 
 	update();
 }
@@ -213,7 +218,7 @@ void CHeroList::CHeroItem::update()
 
 std::shared_ptr<CIntObject> CHeroList::CHeroItem::genSelection()
 {
-	return std::make_shared<CPicture>("HPSYYY", movement->pos.w + 1);
+	return std::make_shared<CPicture>("HPSYYY", movement->pos.w + 1, 0);
 }
 
 void CHeroList::CHeroItem::select(bool on)
@@ -355,13 +360,11 @@ void CTownList::update(const CGTownInstance *)
 
 const SDL_Color & CMinimapInstance::getTileColor(const int3 & pos)
 {
-	static const SDL_Color fogOfWar = {0, 0, 0, 255};
-
 	const TerrainTile * tile = LOCPLINT->cb->getTile(pos, false);
 
 	// if tile is not visible it will be black on minimap
 	if(!tile)
-		return fogOfWar;
+		return Colors::BLACK;
 
 	// if object at tile is owned - it will be colored as its owner
 	for (const CGObjectInstance *obj : tile->blockingObjects)
@@ -410,7 +413,7 @@ void CMinimapInstance::blitTileWithColor(const SDL_Color &color, const int3 &til
 
 	for (int y=yBegin; y<yEnd; y++)
 	{
-		Uint8 *ptr = (Uint8*)to->pixels + y * to->pitch + xBegin * minimap->format->BytesPerPixel;
+		uint8_t *ptr = (uint8_t*)to->pixels + y * to->pitch + xBegin * minimap->format->BytesPerPixel;
 
 		for (int x=xBegin; x<xEnd; x++)
 			ColorPutter<4, 1>::PutColor(ptr, color);
@@ -447,7 +450,7 @@ void CMinimapInstance::drawScaled(int level)
 
 			for (int y=yBegin; y<yEnd; y++)
 			{
-				Uint8 *ptr = (Uint8*)minimap->pixels + y * minimap->pitch + xBegin * minimap->format->BytesPerPixel;
+				uint8_t *ptr = (uint8_t*)minimap->pixels + y * minimap->pitch + xBegin * minimap->format->BytesPerPixel;
 
 				for (int x=xBegin; x<xEnd; x++)
 					ColorPutter<4, 1>::PutColor(ptr, color);
@@ -494,21 +497,8 @@ std::map<TerrainId, std::pair<SDL_Color, SDL_Color> > CMinimap::loadColors()
 
 	for(const auto & terrain : CGI->terrainTypeHandler->objects)
 	{
-		SDL_Color normal =
-		{
-			ui8(terrain->minimapUnblocked[0]),
-			ui8(terrain->minimapUnblocked[1]),
-			ui8(terrain->minimapUnblocked[2]),
-			ui8(255)
-		};
-
-		SDL_Color blocked =
-		{
-			ui8(terrain->minimapBlocked[0]),
-			ui8(terrain->minimapBlocked[1]),
-			ui8(terrain->minimapBlocked[2]),
-			ui8(255)
-		};
+		SDL_Color normal = CSDL_Ext::toSDL(terrain->minimapUnblocked);
+		SDL_Color blocked = CSDL_Ext::toSDL(terrain->minimapBlocked);
 
 		ret[terrain->getId()] = std::make_pair(normal, blocked);
 	}
@@ -795,7 +785,7 @@ CInfoBar::VisibleComponentInfo::VisibleComponentInfo(const Component & compToDis
 {
 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 
-	background = std::make_shared<CPicture>("ADSTATOT", 1);
+	background = std::make_shared<CPicture>("ADSTATOT", 1, 0);
 
 	comp = std::make_shared<CComponent>(compToDisplay);
 	comp->moveTo(Point(pos.x+47, pos.y+50));
@@ -962,7 +952,7 @@ void CInGameConsole::show(SDL_Surface * to)
 {
 	int number = 0;
 
-	std::vector<std::list< std::pair< std::string, Uint32 > >::iterator> toDel;
+	std::vector<std::list< std::pair< std::string, uint32_t > >::iterator> toDel;
 
 	boost::unique_lock<boost::mutex> lock(texts_mx);
 	for(auto it = texts.begin(); it != texts.end(); ++it, ++number)
@@ -1183,9 +1173,9 @@ void CInGameConsole::refreshEnteredText()
 		statusbar->setEnteredText(enteredText);
 }
 
-CAdvMapPanel::CAdvMapPanel(SDL_Surface * bg, Point position)
-	: CIntObject(),
-	  background(bg)
+CAdvMapPanel::CAdvMapPanel(std::shared_ptr<IImage> bg, Point position)
+	: CIntObject()
+	, background(bg)
 {
 	defActions = 255;
 	recActions = 255;
@@ -1193,17 +1183,11 @@ CAdvMapPanel::CAdvMapPanel(SDL_Surface * bg, Point position)
 	pos.y += position.y;
 	if (bg)
 	{
-		pos.w = bg->w;
-		pos.h = bg->h;
+		pos.w = bg->width();
+		pos.h = bg->height();
 	}
 }
 
-CAdvMapPanel::~CAdvMapPanel()
-{
-	if (background)
-		SDL_FreeSurface(background);
-}
-
 void CAdvMapPanel::addChildColorableButton(std::shared_ptr<CButton> button)
 {
 	colorableButtons.push_back(button);
@@ -1221,7 +1205,7 @@ void CAdvMapPanel::setPlayerColor(const PlayerColor & clr)
 void CAdvMapPanel::showAll(SDL_Surface * to)
 {
 	if(background)
-		CSDL_Ext::blitAt(background, pos.x, pos.y, to);
+		background->draw(to, pos.x, pos.y);
 
 	CIntObject::showAll(to);
 }
@@ -1234,7 +1218,7 @@ void CAdvMapPanel::addChildToPanel(std::shared_ptr<CIntObject> obj, ui8 actions)
 	addChild(obj.get(), false);
 }
 
-CAdvMapWorldViewPanel::CAdvMapWorldViewPanel(std::shared_ptr<CAnimation> _icons, SDL_Surface * bg, Point position, int spaceBottom, const PlayerColor &color)
+CAdvMapWorldViewPanel::CAdvMapWorldViewPanel(std::shared_ptr<CAnimation> _icons, std::shared_ptr<IImage> bg, Point position, int spaceBottom, const PlayerColor &color)
 	: CAdvMapPanel(bg, position), icons(_icons)
 {
 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);

+ 5 - 5
client/widgets/AdventureMapClasses.h

@@ -35,6 +35,7 @@ class CComponent;
 class CHeroTooltip;
 class CTownTooltip;
 class CTextBox;
+class IImage;
 
 /// Base UI Element for hero\town lists
 class CList : public CIntObject
@@ -370,10 +371,9 @@ class CAdvMapPanel : public CIntObject
 	std::vector<std::shared_ptr<CButton>> colorableButtons;
 	std::vector<std::shared_ptr<CIntObject>> otherObjects;
 	/// the surface passed to this obj will be freed in dtor
-	SDL_Surface * background;
+	std::shared_ptr<IImage> background;
 public:
-	CAdvMapPanel(SDL_Surface * bg, Point position);
-	virtual ~CAdvMapPanel();
+	CAdvMapPanel(std::shared_ptr<IImage> bg, Point position);
 
 	void addChildToPanel(std::shared_ptr<CIntObject> obj, ui8 actions = 0);
 	void addChildColorableButton(std::shared_ptr<CButton> button);
@@ -394,7 +394,7 @@ class CAdvMapWorldViewPanel : public CAdvMapPanel
 	std::shared_ptr<CFilledTexture> backgroundFiller;
 	std::shared_ptr<CAnimation> icons;
 public:
-	CAdvMapWorldViewPanel(std::shared_ptr<CAnimation> _icons, SDL_Surface * bg, Point position, int spaceBottom, const PlayerColor &color);
+	CAdvMapWorldViewPanel(std::shared_ptr<CAnimation> _icons, std::shared_ptr<IImage> bg, Point position, int spaceBottom, const PlayerColor &color);
 	virtual ~CAdvMapWorldViewPanel();
 
 	void addChildIcon(std::pair<int, Point> data, int indexOffset);
@@ -405,7 +405,7 @@ public:
 class CInGameConsole : public CIntObject
 {
 private:
-	std::list< std::pair< std::string, Uint32 > > texts; //list<text to show, time of add>
+	std::list< std::pair< std::string, uint32_t > > texts; //list<text to show, time of add>
 	boost::mutex texts_mx;		// protects texts
 	std::vector< std::string > previouslyEntered; //previously entered texts, for up/down arrows to work
 	int prevEntDisp; //displayed entry from previouslyEntered - if none it's -1

+ 2 - 0
client/widgets/Buttons.cpp

@@ -24,6 +24,8 @@
 #include "../../lib/CConfigHandler.h"
 #include "../../lib/CGeneralTextHandler.h"
 
+#include <SDL_events.h>
+
 void CButton::update()
 {
 	if (overlay)

+ 2 - 0
client/widgets/Buttons.h

@@ -13,6 +13,8 @@
 #include "../gui/SDL_Extensions.h"
 #include "../../lib/FunctionList.h"
 
+#include <SDL_pixels.h>
+
 VCMI_LIB_NAMESPACE_BEGIN
 
 namespace config

+ 3 - 1
client/widgets/CGarrisonInt.cpp

@@ -32,6 +32,8 @@
 #define SDL_SCANCODE_LCTRL SDL_SCANCODE_LGUI
 #endif
 
+#include <SDL_keyboard.h>
+
 void CGarrisonSlot::setHighlight(bool on)
 {
 	if (on)
@@ -437,7 +439,7 @@ void CGarrisonSlot::splitIntoParts(CGarrisonSlot::EGarrisonType type, int amount
 
 bool CGarrisonSlot::handleSplittingShortcuts()
 {
-	const Uint8 * state = SDL_GetKeyboardState(NULL);
+	const uint8_t * state = SDL_GetKeyboardState(NULL);
 	const bool isAlt = !!state[SDL_SCANCODE_LALT];
 	const bool isLShift = !!state[SDL_SCANCODE_LSHIFT];
 	const bool isLCtrl = !!state[SDL_SCANCODE_LCTRL];

+ 42 - 113
client/widgets/Images.cpp

@@ -13,7 +13,6 @@
 #include "MiscWidgets.h"
 
 #include "../gui/CAnimation.h"
-#include "../gui/SDL_Pixels.h"
 #include "../gui/CGuiHandler.h"
 #include "../gui/CursorHandler.h"
 #include "../gui/ColorFilter.h"
@@ -35,28 +34,37 @@
 #include "../../lib/CGeneralTextHandler.h" //for Unicode related stuff
 #include "../../lib/CRandomGenerator.h"
 
-CPicture::CPicture( SDL_Surface *BG, int x, int y, bool Free )
+CPicture::CPicture(std::shared_ptr<IImage> image, const Point & position)
+	: bg(image)
+	, visible(true)
+	, needRefresh(false)
 {
-	init();
-	bg = BG;
-	freeSurf = Free;
-	pos.x += x;
-	pos.y += y;
-	pos.w = BG->w;
-	pos.h = BG->h;
+	pos += position;
+	pos.w = bg->width();
+	pos.h = bg->height();
 }
 
 CPicture::CPicture( const std::string &bmpname, int x, int y )
+	: CPicture(bmpname, Point(x,y))
+{}
+
+CPicture::CPicture( const std::string &bmpname )
+	: CPicture(bmpname, Point(0,0))
+{}
+
+CPicture::CPicture( const std::string &bmpname, const Point & position )
+	: bg(IImage::createFromFile(bmpname))
+	, visible(true)
+	, needRefresh(false)
 {
-	init();
-	bg = BitmapHandler::loadBitmap(bmpname);
-	freeSurf = true;
-	pos.x += x;
-	pos.y += y;
+	pos.x += position.x;
+	pos.y += position.y;
+
+	assert(bg);
 	if(bg)
 	{
-		pos.w = bg->w;
-		pos.h = bg->h;
+		pos.w = bg->width();
+		pos.h = bg->height();
 	}
 	else
 	{
@@ -64,58 +72,12 @@ CPicture::CPicture( const std::string &bmpname, int x, int y )
 	}
 }
 
-CPicture::CPicture(const Rect &r, const SDL_Color &color, bool screenFormat)
-{
-	init();
-	createSimpleRect(r, screenFormat, SDL_MapRGB(bg->format, color.r, color.g,color.b));
-}
-
-CPicture::CPicture(const Rect &r, ui32 color, bool screenFormat)
+CPicture::CPicture(std::shared_ptr<IImage> image, const Rect &SrcRect, int x, int y)
+	: CPicture(image, Point(x,y))
 {
-	init();
-	createSimpleRect(r, screenFormat, color);
-}
-
-CPicture::CPicture(SDL_Surface * BG, const Rect &SrcRect, int x, int y, bool free)
-{
-	visible = true;
-	needRefresh = false;
-	srcRect = new Rect(SrcRect);
-	pos.x += x;
-	pos.y += y;
+	srcRect = SrcRect;
 	pos.w = srcRect->w;
 	pos.h = srcRect->h;
-	bg = BG;
-	freeSurf = free;
-}
-
-void CPicture::setSurface(SDL_Surface *to)
-{
-	bg = to;
-	if (srcRect)
-	{
-		pos.w = srcRect->w;
-		pos.h = srcRect->h;
-	}
-	else
-	{
-		pos.w = bg->w;
-		pos.h = bg->h;
-	}
-}
-
-CPicture::~CPicture()
-{
-	if(freeSurf)
-		SDL_FreeSurface(bg);
-	delete srcRect;
-}
-
-void CPicture::init()
-{
-	visible = true;
-	needRefresh = false;
-	srcRect = nullptr;
 }
 
 void CPicture::show(SDL_Surface * to)
@@ -127,75 +89,44 @@ void CPicture::show(SDL_Surface * to)
 void CPicture::showAll(SDL_Surface * to)
 {
 	if(bg && visible)
-	{
-		if(srcRect)
-			CSDL_Ext::blitSurface(bg, *srcRect, to, pos.topLeft());
-		else
-			CSDL_Ext::blitAt(bg, pos, to);
-	}
-}
-
-void CPicture::convertToScreenBPP()
-{
-	SDL_Surface *hlp = bg;
-	bg = SDL_ConvertSurface(hlp,screen->format,0);
-	CSDL_Ext::setDefaultColorKey(bg);
-	SDL_FreeSurface(hlp);
+		bg->draw(to, pos.x, pos.y, srcRect.get_ptr());
 }
 
 void CPicture::setAlpha(int value)
 {
-	CSDL_Ext::setAlpha (bg, value);
+	bg->setAlpha(value);
 }
 
 void CPicture::scaleTo(Point size)
 {
-	SDL_Surface * scaled = CSDL_Ext::scaleSurface(bg, size.x, size.y);
+	bg = bg->scaleFast(size);
 
-	if(freeSurf)
-		SDL_FreeSurface(bg);
-
-	setSurface(scaled);
-	freeSurf = false;
-}
-
-void CPicture::createSimpleRect(const Rect &r, bool screenFormat, ui32 color)
-{
-	pos += r.topLeft();
-	pos.w = r.w;
-	pos.h = r.h;
-	if(screenFormat)
-		bg = CSDL_Ext::newSurface(r.w, r.h);
-	else
-		bg = SDL_CreateRGBSurface(0, r.w, r.h, 8, 0, 0, 0, 0);
-
-	SDL_FillRect(bg, nullptr, color);
-	freeSurf = true;
+	pos.w = bg->width();
+	pos.h = bg->height();
 }
 
 void CPicture::colorize(PlayerColor player)
 {
-	assert(bg);
-	graphics->blueToPlayersAdv(bg, player);
+	bg->playerColored(player);
 }
 
 CFilledTexture::CFilledTexture(std::string imageName, Rect position):
     CIntObject(0, position.topLeft()),
-    texture(BitmapHandler::loadBitmap(imageName))
+	texture(IImage::createFromFile(imageName))
 {
 	pos.w = position.w;
 	pos.h = position.h;
 }
 
-CFilledTexture::~CFilledTexture()
-{
-	SDL_FreeSurface(texture);
-}
-
 void CFilledTexture::showAll(SDL_Surface *to)
 {
 	CSDL_Ext::CClipRectGuard guard(to, pos);
-	CSDL_Ext::fillTexture(to, texture);
+
+	for (int y=pos.top(); y < pos.bottom(); y+= texture->height())
+	{
+		for (int x=pos.left(); x < pos.right(); x+=texture->width())
+			texture->draw(to, x, y);
+	}
 }
 
 CAnimImage::CAnimImage(const std::string & name, size_t Frame, size_t Group, int x, int y, ui8 Flags):
@@ -295,7 +226,7 @@ void CAnimImage::showAll(SDL_Surface * to)
 		{
 			if(isScaled())
 			{
-				auto scaled = img->scaleFast(float(scaledSize.x) / img->width());
+				auto scaled = img->scaleFast(scaledSize);
 				scaled->draw(to, pos.x, pos.y);
 			}
 			else
@@ -449,9 +380,7 @@ void CShowableAnim::blitImage(size_t frame, size_t group, SDL_Surface *to)
 	auto img = anim->getImage(frame, group);
 	if(img)
 	{
-		const ColorFilter alphaFilter = ColorFilter::genAlphaShifter(vstd::lerp(0.0f, 1.0f, alpha/255.0f));
-		img->adjustPalette(alphaFilter);
-
+		img->setAlpha(alpha);
 		img->draw(to, pos.x, pos.y, &src);
 	}
 }

+ 28 - 23
client/widgets/Images.h

@@ -12,13 +12,12 @@
 #include "../gui/CIntObject.h"
 #include "../battle/BattleConstants.h"
 
-#include <SDL_render.h>
-
 VCMI_LIB_NAMESPACE_BEGIN
 class Rect;
 VCMI_LIB_NAMESPACE_END
 
 struct SDL_Surface;
+struct SDL_Color;
 class CAnimImage;
 class CLabel;
 class CAnimation;
@@ -27,47 +26,53 @@ class IImage;
 // Image class
 class CPicture : public CIntObject
 {
-	void setSurface(SDL_Surface *to);
+	std::shared_ptr<IImage> bg;
+
 public:
-	SDL_Surface * bg;
-	Rect * srcRect; //if nullptr then whole surface will be used
-	bool freeSurf; //whether surface will be freed upon CPicture destruction
-	bool needRefresh;//Surface needs to be displayed each frame
+	/// if set, only specified section of internal image will be rendered
+	boost::optional<Rect> srcRect;
+
+	/// If set to true, iamge will be redrawn on each frame
+	bool needRefresh;
+
+	/// If set to false, image will not be rendered
+	/// Deprecated, use CIntObject::disable()/enable() instead
 	bool visible;
 
-	SDL_Surface * getSurface()
+	std::shared_ptr<IImage> getSurface()
 	{
 		return bg;
 	}
 
-	CPicture(const Rect & r, const SDL_Color & color, bool screenFormat = false); //rect filled with given color
-	CPicture(const Rect & r, ui32 color, bool screenFormat = false); //rect filled with given color
-	CPicture(SDL_Surface * BG, int x = 0, int y=0, bool Free = true); //wrap existing SDL_Surface
-	CPicture(const std::string &bmpname, int x=0, int y=0);
-	CPicture(SDL_Surface *BG, const Rect &SrcRext, int x = 0, int y = 0, bool free = false); //wrap subrect of given surface
-	~CPicture();
-	void init();
+	/// wrap existing image
+	CPicture(std::shared_ptr<IImage> image, const Point & position);
 
-	//set alpha value for whole surface. Note: may be messed up if surface is shared
-	// 0=transparent, 255=opaque
-	void setAlpha(int value);
+	/// wrap section of an existing Image
+	CPicture(std::shared_ptr<IImage> image, const Rect &SrcRext, int x = 0, int y = 0); //wrap subrect of given surface
 
+	/// Loads image from specified file name
+	CPicture(const std::string & bmpname);
+	CPicture(const std::string & bmpname, const Point & position);
+	CPicture(const std::string & bmpname, int x, int y);
+
+	/// set alpha value for whole surface. Note: may be messed up if surface is shared
+	/// 0=transparent, 255=opaque
+	void setAlpha(int value);
 	void scaleTo(Point size);
-	void createSimpleRect(const Rect &r, bool screenFormat, ui32 color);
+	void colorize(PlayerColor player);
+
 	void show(SDL_Surface * to) override;
 	void showAll(SDL_Surface * to) override;
-	void convertToScreenBPP();
-	void colorize(PlayerColor player);
 };
 
 /// area filled with specific texture
 class CFilledTexture : public CIntObject
 {
-	SDL_Surface * texture;
+	std::shared_ptr<IImage> texture;
 
 public:
 	CFilledTexture(std::string imageName, Rect position);
-	~CFilledTexture();
+
 	void showAll(SDL_Surface *to) override;
 };
 

+ 5 - 8
client/widgets/TextControls.cpp

@@ -24,6 +24,8 @@
 #include "lib/CAndroidVMHelper.h"
 #endif
 
+#include <SDL_events.h>
+
 std::string CLabel::visibleText()
 {
 	return text;
@@ -415,7 +417,7 @@ CGStatusBar::CGStatusBar(int x, int y, std::string name, int maxw)
 	{
 		//execution of this block when maxw is incorrect breaks text centralization (issue #3151)
 		vstd::amin(pos.w, maxw);
-		background->srcRect = new Rect(0, 0, maxw, pos.h);
+		background->srcRect = Rect(0, 0, maxw, pos.h);
 	}
 	autoRedraw = false;
 }
@@ -496,18 +498,13 @@ CTextInput::CTextInput(const Rect & Pos, const Point & bgOffset, const std::stri
 #endif
 }
 
-CTextInput::CTextInput(const Rect & Pos, SDL_Surface * srf)
+CTextInput::CTextInput(const Rect & Pos, std::shared_ptr<IImage> srf)
 	:CFocusable(std::make_shared<CKeyboardFocusListener>(this))
 {
 	pos += Pos.topLeft();
 	captureAllKeys = true;
 	OBJ_CONSTRUCTION;
-	background = std::make_shared<CPicture>(Pos, 0, true);
-	Rect hlp = Pos;
-	if(srf)
-		CSDL_Ext::blitSurface(srf, hlp, background->getSurface(), Point(0,0));
-	else
-		SDL_FillRect(background->getSurface(), nullptr, 0);
+	background = std::make_shared<CPicture>(srf, Pos);
 	pos.w = background->pos.w;
 	pos.h = background->pos.h;
 	background->pos = pos;

+ 4 - 1
client/widgets/TextControls.h

@@ -14,6 +14,9 @@
 #include "../gui/SDL_Extensions.h"
 #include "../../lib/FunctionList.h"
 
+#include <SDL_pixels.h>
+
+class IImage;
 class CSlider;
 
 /// Base class for all text-related widgets.
@@ -218,7 +221,7 @@ public:
 
 	CTextInput(const Rect & Pos, EFonts font, const CFunctionList<void(const std::string &)> & CB);
 	CTextInput(const Rect & Pos, const Point & bgOffset, const std::string & bgName, const CFunctionList<void(const std::string &)> & CB);
-	CTextInput(const Rect & Pos, SDL_Surface * srf = nullptr);
+	CTextInput(const Rect & Pos, std::shared_ptr<IImage> srf);
 
 	void clickLeft(tribool down, bool previousState) override;
 	void keyPressed(const SDL_KeyboardEvent & key) override;

+ 12 - 14
client/windows/CAdvmapInterface.cpp

@@ -55,6 +55,9 @@
 #include "../../lib/mapping/CMapInfo.h"
 #include "../../lib/TerrainHandler.h"
 
+#include <SDL_surface.h>
+#include <SDL_events.h>
+
 #define ADVOPT (conf.go()->ac)
 using namespace CSDL_Ext;
 
@@ -478,8 +481,8 @@ CResDataBar::CResDataBar(const std::string & defname, int x, int y, int offx, in
 	background = std::make_shared<CPicture>(defname, 0, 0);
 	background->colorize(LOCPLINT->playerID);
 
-	pos.w = background->bg->w;
-	pos.h = background->bg->h;
+	pos.w = background->pos.w;
+	pos.h = background->pos.h;
 
 	txtpos.resize(8);
 	for (int i = 0; i < 8 ; i++)
@@ -502,8 +505,8 @@ CResDataBar::CResDataBar()
 	background = std::make_shared<CPicture>(ADVOPT.resdatabarG, 0, 0);
 	background->colorize(LOCPLINT->playerID);
 
-	pos.w = background->bg->w;
-	pos.h = background->bg->h;
+	pos.w = background->pos.w;
+	pos.h = background->pos.h;
 
 	txtpos.resize(8);
 	for (int i = 0; i < 8 ; i++)
@@ -566,10 +569,10 @@ CAdvMapInt::CAdvMapInt():
 	pos.h = screen->h;
 	strongInterest = true; // handle all mouse move events to prevent dead mouse move space in fullscreen mode
 	townList.onSelect = std::bind(&CAdvMapInt::selectionChanged,this);
-	bg = BitmapHandler::loadBitmap(ADVOPT.mainGraphic);
+	bg = IImage::createFromFile(ADVOPT.mainGraphic);
 	if(!ADVOPT.worldViewGraphic.empty())
 	{
-		bgWorldView = BitmapHandler::loadBitmap(ADVOPT.worldViewGraphic);
+		bgWorldView = IImage::createFromFile(ADVOPT.worldViewGraphic);
 	}
 	else
 	{
@@ -579,7 +582,7 @@ CAdvMapInt::CAdvMapInt():
 	if (!bgWorldView)
 	{
 		logGlobal->warn("bgWorldView not defined in resolution config; fallback to VWorld.bmp");
-		bgWorldView = BitmapHandler::loadBitmap("VWorld.bmp");
+		bgWorldView = IImage::createFromFile("VWorld.bmp");
 	}
 
 	worldViewIcons = std::make_shared<CAnimation>("VwSymbol");//todo: customize with ADVOPT
@@ -712,11 +715,6 @@ CAdvMapInt::CAdvMapInt():
 	addUsedEvents(MOVE);
 }
 
-CAdvMapInt::~CAdvMapInt()
-{
-	SDL_FreeSurface(bg);
-}
-
 void CAdvMapInt::fshowOverview()
 {
 	GH.pushIntT<CKingdomInterface>();
@@ -976,7 +974,7 @@ void CAdvMapInt::deactivate()
 
 void CAdvMapInt::showAll(SDL_Surface * to)
 {
-	blitAt(bg,0,0,to);
+	bg->draw(to, 0, 0);
 
 	if(state != INGAME)
 		return;
@@ -1507,7 +1505,7 @@ void CAdvMapInt::startHotSeatWait(PlayerColor Player)
 void CAdvMapInt::setPlayer(PlayerColor Player)
 {
 	player = Player;
-	graphics->blueToPlayersAdv(bg,player);
+	bg->playerColored(player);
 
 	panelMain->setPlayerColor(player);
 	panelWorldView->setPlayerColor(player);

+ 2 - 3
client/windows/CAdvmapInterface.h

@@ -132,7 +132,6 @@ class CAdvMapInt : public CIntObject
 
 public:
 	CAdvMapInt();
-	~CAdvMapInt();
 
 	int3 position; //top left corner of visible map part
 	PlayerColor player;
@@ -170,8 +169,8 @@ public:
 
 	WorldViewOptions worldViewOptions;
 
-	SDL_Surface * bg;
-	SDL_Surface * bgWorldView;
+	std::shared_ptr<IImage> bg;
+	std::shared_ptr<IImage> bgWorldView;
 	std::vector<std::shared_ptr<CAnimImage>> gems;
 	CMinimap minimap;
 	std::shared_ptr<CGStatusBar> statusbar;

+ 34 - 44
client/windows/CCastleInterface.cpp

@@ -24,6 +24,8 @@
 #include "../CPlayerInterface.h"
 #include "../Graphics.h"
 #include "../gui/CGuiHandler.h"
+#include "../gui/CAnimation.h"
+#include "../gui/ColorFilter.h"
 #include "../gui/SDL_Extensions.h"
 #include "../widgets/MiscWidgets.h"
 #include "../widgets/CComponent.h"
@@ -42,6 +44,8 @@
 #include "../../lib/mapObjects/CGHeroInstance.h"
 #include "../../lib/mapObjects/CGTownInstance.h"
 
+#include <SDL_events.h>
+
 CBuildingRect::CBuildingRect(CCastleBuildings * Par, const CGTownInstance * Town, const CStructure * Str)
 	: CShowableAnim(0, 0, Str->defName, CShowableAnim::BASE),
 	  parent(Par),
@@ -68,24 +72,16 @@ CBuildingRect::CBuildingRect(CCastleBuildings * Par, const CGTownInstance * Town
 	}
 
 	if(!str->borderName.empty())
-		border = BitmapHandler::loadBitmap(str->borderName);
+		border = IImage::createFromFile(str->borderName);
 	else
 		border = nullptr;
 
 	if(!str->areaName.empty())
-		area = BitmapHandler::loadBitmap(str->areaName);
+		area = IImage::createFromFile(str->areaName);
 	else
 		area = nullptr;
 }
 
-CBuildingRect::~CBuildingRect()
-{
-	if(border)
-		SDL_FreeSurface(border);
-	if(area)
-		SDL_FreeSurface(area);
-}
-
 const CBuilding * CBuildingRect::getBuilding()
 {
 	if (!str->building)
@@ -127,7 +123,7 @@ void CBuildingRect::clickLeft(tribool down, bool previousState)
 {
 	if(previousState && getBuilding() && area && !down && (parent->selectedBuilding==this))
 	{
-		if(!CSDL_Ext::isTransparent(area, GH.getCursorPosition() - pos.topLeft())) //inside building image
+		if(!area->isTransparent(GH.getCursorPosition() - pos.topLeft())) //inside building image
 		{
 			auto building = getBuilding();
 			parent->buildingClicked(building->bid, building->subId, building->upgrade);
@@ -139,7 +135,7 @@ void CBuildingRect::clickRight(tribool down, bool previousState)
 {
 	if((!area) || (!((bool)down)) || (this!=parent->selectedBuilding) || getBuilding() == nullptr)
 		return;
-	if( !CSDL_Ext::isTransparent(area, GH.getCursorPosition() - pos.topLeft()) ) //inside building image
+	if( !area->isTransparent(GH.getCursorPosition() - pos.topLeft()) ) //inside building image
 	{
 		BuildingID bid = getBuilding()->bid;
 		const CBuilding *bld = town->town->buildings.at(bid);
@@ -159,10 +155,10 @@ void CBuildingRect::clickRight(tribool down, bool previousState)
 SDL_Color multiplyColors(const SDL_Color & b, const SDL_Color & a, double f)
 {
 	SDL_Color ret;
-	ret.r = static_cast<Uint8>(a.r * f + b.r * (1 - f));
-	ret.g = static_cast<Uint8>(a.g * f + b.g * (1 - f));
-	ret.b = static_cast<Uint8>(a.b * f + b.b * (1 - f));
-	ret.a = static_cast<Uint8>(a.a * f + b.b * (1 - f));
+	ret.r = static_cast<uint8_t>(a.r * f + b.r * (1 - f));
+	ret.g = static_cast<uint8_t>(a.g * f + b.g * (1 - f));
+	ret.b = static_cast<uint8_t>(a.b * f + b.b * (1 - f));
+	ret.a = static_cast<uint8_t>(a.a * f + b.b * (1 - f));
 	return ret;
 }
 
@@ -186,33 +182,27 @@ void CBuildingRect::show(SDL_Surface * to)
 		if(stateTimeCounter >= BUILD_ANIMATION_FINISHED_TIMEPOINT)
 		{
 			if(parent->selectedBuilding == this)
-				blitAtLoc(border,0,0,to);
+				border->draw(to, pos.x, pos.y);
 			return;
 		}
-		if(border->format->palette != nullptr)
-		{
-			// key colors in glowing border
-			SDL_Color c1 = {200, 200, 200, 255};
-			SDL_Color c2 = {120, 100,  60, 255};
-			SDL_Color c3 = {200, 180, 110, 255};
 
-			ui32 colorID = SDL_MapRGB(border->format, c3.r, c3.g, c3.b);
-			SDL_Color oldColor = border->format->palette->colors[colorID];
-			SDL_Color newColor;
+		auto darkBorder = ColorFilter::genRangeShifter(0.f, 0.f, 0.f, 0.5f, 0.5f, 0.5f );
+		auto lightBorder = ColorFilter::genRangeShifter(0.f, 0.f, 0.f, 2.0f, 2.0f, 2.0f );
+		auto baseBorder = ColorFilter::genEmptyShifter();
 
-			if (stateTimeCounter < BUILDING_WHITE_BORDER_TIMEPOINT)
-				newColor = multiplyColors(c1, c2, static_cast<double>(stateTimeCounter % stageDelay) / stageDelay);
-			else
-			if (stateTimeCounter < BUILDING_YELLOW_BORDER_TIMEPOINT)
-				newColor = multiplyColors(c2, c3, static_cast<double>(stateTimeCounter % stageDelay) / stageDelay);
-			else
-				newColor = oldColor;
+		float progress = float(stateTimeCounter % stageDelay) / stageDelay;
 
-			CSDL_Ext::setColors(border, &newColor, colorID, 1);
-			blitAtLoc(border, 0, 0, to);
-			CSDL_Ext::setColors(border, &oldColor, colorID, 1);
-		}
+		if (stateTimeCounter < BUILDING_WHITE_BORDER_TIMEPOINT)
+			border->adjustPalette(ColorFilter::genInterpolated(lightBorder, darkBorder, progress), 0);
+		else
+		if (stateTimeCounter < BUILDING_YELLOW_BORDER_TIMEPOINT)
+			border->adjustPalette(ColorFilter::genInterpolated(darkBorder, baseBorder, progress), 0);
+		else
+			border->adjustPalette(baseBorder, 0);
+
+		border->draw(to, pos.x, pos.y);
 	}
+
 	if(stateTimeCounter < BUILD_ANIMATION_FINISHED_TIMEPOINT)
 		stateTimeCounter += GH.mainFPSmng->getElapsedMilliseconds();
 }
@@ -224,7 +214,7 @@ void CBuildingRect::showAll(SDL_Surface * to)
 
 	CShowableAnim::showAll(to);
 	if(!active && parent->selectedBuilding == this && border)
-		blitAtLoc(border,0,0,to);
+		border->draw(to, pos.x, pos.y);
 }
 
 std::string CBuildingRect::getSubtitle()//hover text for building
@@ -256,7 +246,7 @@ void CBuildingRect::mouseMoved (const SDL_MouseMotionEvent & sEvent)
 {
 	if(area && pos.isInside(sEvent.x, sEvent.y))
 	{
-		if(CSDL_Ext::isTransparent(area, GH.getCursorPosition() - pos.topLeft())) //hovered pixel is inside this building
+		if(area->isTransparent(GH.getCursorPosition() - pos.topLeft())) //hovered pixel is inside this building
 		{
 			if(parent->selectedBuilding == this)
 			{
@@ -1168,7 +1158,7 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, const CGTownInst
 	garr->addSplitBtn(split);
 
 	Rect barRect(9, 182, 732, 18);
-	auto statusbarBackground = std::make_shared<CPicture>(panel->getSurface(), barRect, 9, 555, false);
+	auto statusbarBackground = std::make_shared<CPicture>(panel->getSurface(), barRect, 9, 555);
 	statusbar = CGStatusBar::create(statusbarBackground);
 	resdatabar = std::make_shared<CResDataBar>("ARESBAR", 3, 575, 32, 2, 85, 85);
 
@@ -1365,7 +1355,7 @@ CHallInterface::CHallInterface(const CGTownInstance * Town):
 	resdatabar->moveBy(pos.topLeft(), true);
 	Rect barRect(5, 556, 740, 18);
 
-	auto statusbarBackground = std::make_shared<CPicture>(background->getSurface(), barRect, 5, 556, false);
+	auto statusbarBackground = std::make_shared<CPicture>(background->getSurface(), barRect, 5, 556);
 	statusbar = CGStatusBar::create(statusbarBackground);
 
 	title = std::make_shared<CLabel>(399, 12, FONT_MEDIUM, ETextAlignment::CENTER, Colors::WHITE, town->town->buildings.at(BuildingID(town->hallLevel()+BuildingID::VILLAGE_HALL))->getNameTranslated());
@@ -1588,7 +1578,7 @@ CFortScreen::CFortScreen(const CGTownInstance * town):
 
 	Rect barRect(4, 554, 740, 18);
 
-	auto statusbarBackground = std::make_shared<CPicture>(background->getSurface(), barRect, 4, 554, false);
+	auto statusbarBackground = std::make_shared<CPicture>(background->getSurface(), barRect, 4, 554);
 	statusbar = CGStatusBar::create(statusbarBackground);
 }
 
@@ -1729,7 +1719,7 @@ CMageGuildScreen::CMageGuildScreen(CCastleInterface * owner,std::string imagem)
 
 	Rect barRect(7, 556, 737, 18);
 
-	auto statusbarBackground = std::make_shared<CPicture>(background->getSurface(), barRect, 7, 556, false);
+	auto statusbarBackground = std::make_shared<CPicture>(background->getSurface(), barRect, 7, 556);
 	statusbar = CGStatusBar::create(statusbarBackground);
 
 	exit = std::make_shared<CButton>(Point(748, 556), "TPMAGE1.DEF", CButton::tooltip(CGI->generaltexth->allTexts[593]), [&](){ close(); }, SDLK_RETURN);
@@ -1796,7 +1786,7 @@ CBlacksmithDialog::CBlacksmithDialog(bool possible, CreatureID creMachineID, Art
 
 	Rect barRect(8, pos.h - 26, pos.w - 16, 19);
 
-	auto statusbarBackground = std::make_shared<CPicture>(background->getSurface(), barRect, 8, pos.h - 26, false);
+	auto statusbarBackground = std::make_shared<CPicture>(background->getSurface(), barRect, 8, pos.h - 26);
 	statusbar = CGStatusBar::create(statusbarBackground);
 
 	animBG = std::make_shared<CPicture>("TPSMITBK", 64, 50);

+ 2 - 3
client/windows/CCastleInterface.h

@@ -56,13 +56,12 @@ public:
 	CCastleBuildings * parent;
 	const CGTownInstance * town;
 	const CStructure* str;
-	SDL_Surface* border;
-	SDL_Surface* area;
+	std::shared_ptr<IImage> border;
+	std::shared_ptr<IImage> area;
 
 	ui32 stateTimeCounter;//For building construction - current stage in animation
 
 	CBuildingRect(CCastleBuildings * Par, const CGTownInstance *Town, const CStructure *Str);
-	~CBuildingRect();
 	bool operator<(const CBuildingRect & p2) const;
 	void hover(bool on) override;
 	void clickLeft(tribool down, bool previousState) override;

+ 5 - 4
client/windows/CSpellWindow.cpp

@@ -42,6 +42,8 @@
 
 #include "../../lib/mapObjects/CGHeroInstance.h"
 
+#include <SDL_events.h>
+
 CSpellWindow::InteractiveArea::InteractiveArea(const Rect & myRect, std::function<void()> funcL, int helpTextId, CSpellWindow * _owner)
 {
 	addUsedEvents(LCLICK | RCLICK | HOVER);
@@ -206,9 +208,9 @@ CSpellWindow::CSpellWindow(const CGHeroInstance * _myHero, CPlayerInterface * _m
 	temp_rect = CSDL_Ext::genRect(36, 56, 549 + pos.x, 330 + pos.y);
 	interactiveAreas.push_back(std::make_shared<InteractiveArea>(temp_rect, std::bind(&CSpellWindow::selectSchool, this, 4), 458, this));
 
-	temp_rect = CSDL_Ext::genRect(leftCorner->bg->h, leftCorner->bg->w, 97 + pos.x, 77 + pos.y);
+	temp_rect = CSDL_Ext::genRect(leftCorner->pos.h, leftCorner->pos.w, 97 + pos.x, 77 + pos.y);
 	interactiveAreas.push_back(std::make_shared<InteractiveArea>(temp_rect, std::bind(&CSpellWindow::fLcornerb, this), 450, this));
-	temp_rect = CSDL_Ext::genRect(rightCorner->bg->h, rightCorner->bg->w, 487 + pos.x, 72 + pos.y);
+	temp_rect = CSDL_Ext::genRect(rightCorner->pos.h, rightCorner->pos.w, 487 + pos.x, 72 + pos.y);
 	interactiveAreas.push_back(std::make_shared<InteractiveArea>(temp_rect, std::bind(&CSpellWindow::fRcornerb, this), 451, this));
 
 	//areas for spells
@@ -640,9 +642,8 @@ void CSpellWindow::SpellArea::setSpell(const CSpell * spell)
 		SDL_Color firstLineColor, secondLineColor;
 		if(spellCost > owner->myHero->mana) //hero cannot cast this spell
 		{
-			static const SDL_Color unavailableSpell = {239, 189, 33, 0};
 			firstLineColor = Colors::WHITE;
-			secondLineColor = unavailableSpell;
+			secondLineColor = Colors::ORANGE;
 		}
 		else
 		{

+ 1 - 1
client/windows/CSpellWindow.h

@@ -84,7 +84,7 @@ class CSpellWindow : public CWindowObject
 	int sitesPerTabBattle[5];
 
 	bool battleSpellsOnly; //if true, only battle spells are displayed; if false, only adventure map spells are displayed
-	Uint8 selectedTab; // 0 - air magic, 1 - fire magic, 2 - water magic, 3 - earth magic, 4 - all schools
+	uint8_t selectedTab; // 0 - air magic, 1 - fire magic, 2 - water magic, 3 - earth magic, 4 - all schools
 	int currentPage; //changes when corners are clicked
 	std::vector<const CSpell *> mySpells; //all spels in this spellbook
 

+ 1 - 1
client/windows/CTradeWindow.cpp

@@ -679,7 +679,7 @@ CMarketplaceWindow::CMarketplaceWindow(const IMarket * Market, const CGHeroInsta
 
 			// create image that copies part of background containing slot MISC_1 into position of slot MISC_5
 			// this is workaround for bug in H3 files where this slot for ragdoll on this screen is missing
-			images.push_back(std::make_shared<CPicture>(background->bg, Rect(20, 187, 47, 47), 18, 339 ));
+			images.push_back(std::make_shared<CPicture>(background->getSurface(), Rect(20, 187, 47, 47), 18, 339 ));
 			sliderNeeded = false;
 			break;
 		default:

+ 12 - 6
client/windows/CWindowObject.cpp

@@ -15,10 +15,11 @@
 #include "../widgets/MiscWidgets.h"
 #include "../widgets/Images.h"
 
-#include "../gui/SDL_Pixels.h"
+#include "../gui/SDL_PixelAccess.h"
 #include "../gui/SDL_Extensions.h"
 #include "../gui/CGuiHandler.h"
 #include "../gui/CursorHandler.h"
+#include "../gui/CAnimation.h"
 
 #include "../battle/BattleInterface.h"
 #include "../battle/BattleInterfaceClasses.h"
@@ -34,6 +35,8 @@
 #include "../../lib/CConfigHandler.h"
 #include "../../lib/CGeneralTextHandler.h" //for Unicode related stuff
 
+#include <SDL_surface.h>
+
 CWindowObject::CWindowObject(int options_, std::string imageName, Point centerAt):
 	WindowBase(getUsedEvents(options_), Point()),
 	options(options_),
@@ -137,7 +140,7 @@ void CWindowObject::setShadow(bool on)
 		//helper to set last row
 		auto blitAlphaRow = [](SDL_Surface *surf, size_t row)
 		{
-			Uint8 * ptr = (Uint8*)surf->pixels + surf->pitch * (row);
+			uint8_t * ptr = (uint8_t*)surf->pixels + surf->pitch * (row);
 
 			for (size_t i=0; i< surf->w; i++)
 			{
@@ -149,7 +152,7 @@ void CWindowObject::setShadow(bool on)
 		// helper to set last column
 		auto blitAlphaCol = [](SDL_Surface *surf, size_t col)
 		{
-			Uint8 * ptr = (Uint8*)surf->pixels + 4 * (col);
+			uint8_t * ptr = (uint8_t*)surf->pixels + 4 * (col);
 
 			for (size_t i=0; i< surf->h; i++)
 			{
@@ -213,11 +216,14 @@ void CWindowObject::setShadow(bool on)
 		{
 			OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
 
-			shadowParts.push_back(std::make_shared<CPicture>(shadowCorner, shadowPos.x, shadowPos.y));
-			shadowParts.push_back(std::make_shared<CPicture>(shadowRight, shadowPos.x, shadowStart.y));
-			shadowParts.push_back(std::make_shared<CPicture>(shadowBottom, shadowStart.x, shadowPos.y));
+			shadowParts.push_back(std::make_shared<CPicture>( IImage::createFromSurface(shadowCorner), Point(shadowPos.x,   shadowPos.y)));
+			shadowParts.push_back(std::make_shared<CPicture>( IImage::createFromSurface(shadowRight ),  Point(shadowPos.x,   shadowStart.y)));
+			shadowParts.push_back(std::make_shared<CPicture>( IImage::createFromSurface(shadowBottom), Point(shadowStart.x, shadowPos.y)));
 
 		}
+		SDL_FreeSurface(shadowCorner);
+		SDL_FreeSurface(shadowBottom);
+		SDL_FreeSurface(shadowRight);
 	}
 }
 

+ 3 - 2
client/windows/GUIClasses.cpp

@@ -61,6 +61,8 @@
 #include "../lib/NetPacksBase.h"
 #include "../lib/StartInfo.h"
 
+#include <SDL_events.h>
+
 using namespace CSDL_Ext;
 
 std::list<CFocusable*> CFocusable::focusables;
@@ -1208,7 +1210,7 @@ CExchangeWindow::CExchangeWindow(ObjectInstanceID hero1, ObjectInstanceID hero2,
 	questlogButton[1] = std::make_shared<CButton>(Point(740, qeLayout ? 39 : 44), "hsbtns4.def", CButton::tooltip(CGI->generaltexth->heroscrn[0]), std::bind(&CExchangeWindow::questlog, this, 1));
 
 	Rect barRect(5, 578, 725, 18);
-	statusbar = CGStatusBar::create(std::make_shared<CPicture>(background->getSurface(), barRect, 5, 578, false));
+	statusbar = CGStatusBar::create(std::make_shared<CPicture>(background->getSurface(), barRect, 5, 578));
 
 	//garrison interface
 
@@ -1368,7 +1370,6 @@ CPuzzleWindow::CPuzzleWindow(const int3 & GrailPos, double discoveredRatio)
 			piecesToRemove.push_back(piece);
 			piece->needRefresh = true;
 			piece->recActions = piece->recActions & ~SHOWALL;
-			SDL_SetSurfaceBlendMode(piece->bg,SDL_BLENDMODE_BLEND);
 		}
 		else
 		{

+ 2 - 1
client/windows/InfoWindows.cpp

@@ -21,7 +21,6 @@
 #include "../widgets/CComponent.h"
 #include "../widgets/MiscWidgets.h"
 
-#include "../gui/SDL_Pixels.h"
 #include "../gui/SDL_Extensions.h"
 #include "../gui/CGuiHandler.h"
 #include "../gui/CursorHandler.h"
@@ -39,6 +38,8 @@
 #include "../../lib/mapObjects/CGTownInstance.h"
 #include "../../lib/mapObjects/MiscObjects.h"
 
+#include <SDL_surface.h>
+
 void CSimpleWindow::show(SDL_Surface * to)
 {
 	if(bitmap)

+ 1 - 0
cmake_modules/VCMI_lib.cmake

@@ -414,6 +414,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
 		${MAIN_LIB_DIR}/CModHandler.h
 		${MAIN_LIB_DIR}/CondSh.h
 		${MAIN_LIB_DIR}/ConstTransitivePtr.h
+		${MAIN_LIB_DIR}/Color.h
 		${MAIN_LIB_DIR}/CPathfinder.h
 		${MAIN_LIB_DIR}/CPlayerState.h
 		${MAIN_LIB_DIR}/CRandomGenerator.h

+ 9 - 9
lib/CCreatureHandler.cpp

@@ -927,15 +927,15 @@ void CCreatureHandler::loadCreatureJson(CCreature * creature, const JsonNode & c
 	{
 		CCreature::CreatureAnimation::RayColor color;
 
-		color.r1 = value["start"].Vector()[0].Integer();
-		color.g1 = value["start"].Vector()[1].Integer();
-		color.b1 = value["start"].Vector()[2].Integer();
-		color.a1 = value["start"].Vector()[3].Integer();
-
-		color.r2 = value["end"].Vector()[0].Integer();
-		color.g2 = value["end"].Vector()[1].Integer();
-		color.b2 = value["end"].Vector()[2].Integer();
-		color.a2 = value["end"].Vector()[3].Integer();
+		color.start.r = value["start"].Vector()[0].Integer();
+		color.start.g = value["start"].Vector()[1].Integer();
+		color.start.b = value["start"].Vector()[2].Integer();
+		color.start.a = value["start"].Vector()[3].Integer();
+
+		color.end.r = value["end"].Vector()[0].Integer();
+		color.end.g = value["end"].Vector()[1].Integer();
+		color.end.b = value["end"].Vector()[2].Integer();
+		color.end.a = value["end"].Vector()[3].Integer();
 
 		creature->animation.projectileRay.push_back(color);
 	}

+ 4 - 3
lib/CCreatureHandler.h

@@ -19,6 +19,7 @@
 #include "JsonNode.h"
 #include "IHandlerBase.h"
 #include "CRandomGenerator.h"
+#include "Color.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
@@ -63,12 +64,12 @@ public:
 	struct CreatureAnimation
 	{
 		struct RayColor {
-			uint8_t r1, g1, b1, a1;
-			uint8_t r2, g2, b2, a2;
+			ColorRGBA start;
+			ColorRGBA end;
 
 			template <typename Handler> void serialize(Handler &h, const int version)
 			{
-				h & r1 & g1 & b1 & a1 & r2 & g2 & b2 & a2;
+				h & start & end;
 			}
 		};
 

+ 62 - 0
lib/Color.h

@@ -0,0 +1,62 @@
+/*
+ * Color.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+#pragma once
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+/// An object that represents RGBA color
+class ColorRGBA
+{
+public:
+	enum : uint8_t
+	{
+		ALPHA_OPAQUE = 255,
+		ALPHA_TRANSPARENT = 0,
+	};
+
+	uint8_t r;
+	uint8_t g;
+	uint8_t b;
+	uint8_t a;
+
+	//constructors
+	ColorRGBA()
+		:r(0)
+		,g(0)
+		,b(0)
+		,a(0)
+	{
+	}
+
+	ColorRGBA(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
+		: r(r)
+		, g(g)
+		, b(b)
+		, a(a)
+	{}
+
+	ColorRGBA(uint8_t r, uint8_t g, uint8_t b)
+		: r(r)
+		, g(g)
+		, b(b)
+		, a(ALPHA_OPAQUE)
+	{}
+
+	template <typename Handler>
+	void serialize(Handler &h, const int version)
+	{
+		h & r;
+		h & g;
+		h & b;
+		h & a;
+	}
+};
+
+VCMI_LIB_NAMESPACE_END

+ 3 - 2
lib/TerrainHandler.h

@@ -14,6 +14,7 @@
 #include <vcmi/Entity.h>
 #include "GameConstants.h"
 #include "IHandlerBase.h"
+#include "Color.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
@@ -46,8 +47,8 @@ public:
 	
 	std::vector<BattleField> battleFields;
 	std::vector<TerrainId> prohibitTransitions;
-	std::array<int, 3> minimapBlocked;
-	std::array<int, 3> minimapUnblocked;
+	ColorRGBA minimapBlocked;
+	ColorRGBA minimapUnblocked;
 	std::string shortIdentifier;
 	std::string musicFilename;
 	std::string tilesFilename;

+ 1 - 1
mapeditor/maphandler.cpp

@@ -433,7 +433,7 @@ QRgb MapHandler::getTileColor(int x, int y, int z)
 	if (tile.blocked && (!tile.visitable))
 		color = tile.terType->minimapBlocked;
 	
-	return qRgb(color[0], color[1], color[2]);
+	return qRgb(color.r, color.g, color.b);
 }
 
 void MapHandler::drawMinimapTile(QPainter & painter, int x, int y, int z)