Browse Source

Refactoring of SDL API usage:

- Rect no longer inherits from SDL_Rect
- renamed vcmi functions that used SDL naming format
- moved all functions in SDL_Extensions file into CSDL_Ext namespace
- SDL_Rect is now used only by SDL_Extensions, all other code uses Rect
Ivan Savenko 2 years ago
parent
commit
ee7a573cb8
56 changed files with 770 additions and 448 deletions
  1. 5 1
      client/CMT.h
  2. 1 3
      client/CMessage.cpp
  3. 7 5
      client/CVideoHandler.cpp
  4. 5 6
      client/CVideoHandler.h
  5. 1 1
      client/Graphics.cpp
  6. 1 1
      client/battle/BattleAnimationClasses.h
  7. 2 2
      client/battle/BattleFieldController.h
  8. 3 3
      client/battle/BattleInterfaceClasses.cpp
  9. 1 1
      client/battle/BattleObstacleController.h
  10. 1 1
      client/battle/BattleProjectileController.h
  11. 1 1
      client/battle/BattleSiegeController.h
  12. 2 1
      client/battle/BattleStacksController.cpp
  13. 1 0
      client/battle/CreatureAnimation.cpp
  14. 10 15
      client/gui/CAnimation.cpp
  15. 3 2
      client/gui/CAnimation.h
  16. 316 0
      client/gui/CCursorHandler.cpp
  17. 8 7
      client/gui/CGuiHandler.cpp
  18. 4 2
      client/gui/CGuiHandler.h
  19. 3 11
      client/gui/CIntObject.cpp
  20. 2 3
      client/gui/CIntObject.h
  21. 6 4
      client/gui/Canvas.cpp
  22. 1 1
      client/gui/ColorFilter.cpp
  23. 3 5
      client/gui/CursorHandler.cpp
  24. 6 7
      client/gui/Fonts.cpp
  25. 1 1
      client/gui/Fonts.h
  26. 3 2
      client/gui/NotificationHandler.h
  27. 136 93
      client/gui/SDL_Extensions.cpp
  28. 70 106
      client/gui/SDL_Extensions.h
  29. 12 2
      client/gui/SDL_Pixels.h
  30. 3 2
      client/mainmenu/CMainMenu.cpp
  31. 1 1
      client/mainmenu/CPrologEpilogVideo.cpp
  32. 42 42
      client/mapHandler.cpp
  33. 14 15
      client/mapHandler.h
  34. 9 9
      client/widgets/AdventureMapClasses.cpp
  35. 9 6
      client/widgets/Buttons.cpp
  36. 1 2
      client/widgets/Buttons.h
  37. 4 4
      client/widgets/CArtifactHolder.cpp
  38. 1 1
      client/widgets/CComponent.cpp
  39. 2 9
      client/widgets/Images.cpp
  40. 3 2
      client/widgets/Images.h
  41. 1 1
      client/widgets/ObjectLists.h
  42. 3 3
      client/widgets/TextControls.cpp
  43. 11 11
      client/windows/CAdvmapInterface.cpp
  44. 1 1
      client/windows/CAdvmapInterface.h
  45. 3 3
      client/windows/CCastleInterface.cpp
  46. 2 2
      client/windows/CKingdomInterface.cpp
  47. 2 2
      client/windows/CQuestLog.cpp
  48. 14 14
      client/windows/CSpellWindow.cpp
  49. 2 3
      client/windows/CSpellWindow.h
  50. 5 5
      client/windows/CTradeWindow.cpp
  51. 3 5
      client/windows/CWindowObject.cpp
  52. 11 11
      client/windows/GUIClasses.cpp
  53. 1 0
      client/windows/GUIClasses.h
  54. 3 3
      client/windows/InfoWindows.cpp
  55. 1 1
      client/windows/InfoWindows.h
  56. 3 3
      lib/Rect.h

+ 5 - 1
client/CMT.h

@@ -8,7 +8,11 @@
  *
  */
 #pragma once
-#include <SDL_render.h>
+
+struct SDL_Texture;
+struct SDL_Window;
+struct SDL_Renderer;
+struct SDL_Surface;
 
 extern SDL_Texture * screenTexture;
 

+ 1 - 3
client/CMessage.cpp

@@ -102,9 +102,7 @@ SDL_Surface * CMessage::drawDialogBox(int w, int h, PlayerColor playerColor)
 	{
 		for (int j=0; j<h; j+=background->h)
 		{
-			Rect srcR(0,0,background->w, background->h);
-			Rect dstR(i,j,w,h);
-			CSDL_Ext::blitSurface(background, &srcR, ret, &dstR);
+			CSDL_Ext::blitSurface(background, ret, Point(i,j));
 		}
 	}
 	drawBorder(playerColor, ret, w, h);

+ 7 - 5
client/CVideoHandler.cpp

@@ -67,8 +67,8 @@ CVideoPlayer::CVideoPlayer()
 	context = nullptr;
 	texture = nullptr;
 	dest = nullptr;
-	destRect = genRect(0,0,0,0);
-	pos = genRect(0,0,0,0);
+	destRect = CSDL_Ext::genRect(0,0,0,0);
+	pos = CSDL_Ext::genRect(0,0,0,0);
 	refreshWait = 0;
 	refreshCount = 0;
 	doLoop = false;
@@ -339,10 +339,10 @@ void CVideoPlayer::show( int x, int y, SDL_Surface *dst, bool update )
 
 	pos.x = x;
 	pos.y = y;
-	CSDL_Ext::blitSurface(dest, &destRect, dst, &pos);
+	CSDL_Ext::blitSurface(dest, destRect, dst, pos.topLeft());
 
 	if (update)
-		SDL_UpdateRect(dst, pos.x, pos.y, pos.w, pos.h);
+		CSDL_Ext::updateRect(dst, pos);
 }
 
 void CVideoPlayer::redraw( int x, int y, SDL_Surface *dst, bool update )
@@ -442,7 +442,9 @@ bool CVideoPlayer::playVideo(int x, int y, bool stopOnKey)
 		if(stopOnKey && keyDown())
 			return false;
 
-		SDL_RenderCopy(mainRenderer, texture, nullptr, &pos);
+		SDL_Rect rect = Geometry::toSDL(pos);
+
+		SDL_RenderCopy(mainRenderer, texture, nullptr, &rect);
 		SDL_RenderPresent(mainRenderer);
 
 		// Wait 3 frames

+ 5 - 6
client/CVideoHandler.h

@@ -9,8 +9,10 @@
  */
 #pragma once
 
-struct SDL_Surface;
+#include "../lib/Rect.h"
 
+struct SDL_Surface;
+struct SDL_Texture;
 
 class IVideoPlayer
 {
@@ -54,9 +56,6 @@ public:
 
 #include "../lib/filesystem/CInputStream.h"
 
-#include <SDL.h>
-#include <SDL_video.h>
-
 extern "C" {
 #include <libavformat/avformat.h>
 #include <libavcodec/avcodec.h>
@@ -106,8 +105,8 @@ class CVideoPlayer : public IMainVideoPlayer
 
 	SDL_Texture *texture;
 	SDL_Surface *dest;
-	SDL_Rect destRect;			// valid when dest is used
-	SDL_Rect pos;				// destination on screen
+	Rect destRect;			// valid when dest is used
+	Rect pos;				// destination on screen
 
 	int refreshWait; // Wait several refresh before updating the image
 	int refreshCount;

+ 1 - 1
client/Graphics.cpp

@@ -286,7 +286,7 @@ void Graphics::blueToPlayersAdv(SDL_Surface * sur, PlayerColor player)
 //FIXME: not all player colored images have player palette at last 32 indexes
 //NOTE: following code is much more correct but still not perfect (bugged with status bar)
 
-		SDL_SetColors(sur, palette, 224, 32);
+		CSDL_Ext::setColors(sur, palette, 224, 32);
 
 
 #if 0

+ 1 - 1
client/battle/BattleAnimationClasses.h

@@ -28,7 +28,7 @@ class CAnimation;
 class BattleInterface;
 class CreatureAnimation;
 struct StackAttackedInfo;
-struct Point;
+class Point;
 
 /// Base class of battle animations
 class BattleAnimation

+ 2 - 2
client/battle/BattleFieldController.h

@@ -18,8 +18,8 @@ class CStack;
 
 VCMI_LIB_NAMESPACE_END
 
-struct Rect;
-struct Point;
+class Rect;
+class Point;
 
 class ClickableHex;
 class BattleHero;

+ 3 - 3
client/battle/BattleInterfaceClasses.cpp

@@ -160,7 +160,7 @@ void BattleConsole::setEnteringMode(bool on)
 	if (on)
 	{
 		assert(enteringText == false);
-		CSDL_Ext::startTextInput(&pos);
+		CSDL_Ext::startTextInput(pos);
 	}
 	else
 	{
@@ -494,7 +494,7 @@ BattleResultWindow::BattleResultWindow(const BattleResult & br, CPlayerInterface
 {
 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 
-	pos = genRect(561, 470, (screen->w - 800)/2 + 165, (screen->h - 600)/2 + 19);
+	pos = CSDL_Ext::genRect(561, 470, (screen->w - 800)/2 + 165, (screen->h - 600)/2 + 19);
 	background = std::make_shared<CPicture>("CPRESULT");
 	background->colorize(owner.playerID);
 
@@ -850,7 +850,7 @@ void StackQueue::StackBox::setUnit(const battle::Unit * unit, size_t turn)
 		if (unit->unitType()->idNumber == CreatureID::ARROW_TOWERS)
 			icon->setFrame(owner->getSiegeShooterIconID(), 1);
 
-		amount->setText(makeNumberShort(unit->getCount()));
+		amount->setText(CSDL_Ext::makeNumberShort(unit->getCount()));
 
 		if(stateIcon)
 		{

+ 1 - 1
client/battle/BattleObstacleController.h

@@ -21,7 +21,7 @@ class Canvas;
 class CAnimation;
 class BattleInterface;
 class BattleRenderer;
-struct Point;
+class Point;
 
 /// Controls all currently active projectiles on the battlefield
 /// (with exception of moat, which is apparently handled by siege controller)

+ 1 - 1
client/battle/BattleProjectileController.h

@@ -19,7 +19,7 @@ class CSpell;
 
 VCMI_LIB_NAMESPACE_END
 
-struct Point;
+class Point;
 class CAnimation;
 class Canvas;
 class BattleInterface;

+ 1 - 1
client/battle/BattleSiegeController.h

@@ -21,7 +21,7 @@ class CGTownInstance;
 
 VCMI_LIB_NAMESPACE_END
 
-struct Point;
+class Point;
 class Canvas;
 class BattleInterface;
 class BattleRenderer;

+ 2 - 1
client/battle/BattleStacksController.cpp

@@ -28,6 +28,7 @@
 #include "../gui/CAnimation.h"
 #include "../gui/CGuiHandler.h"
 #include "../gui/Canvas.h"
+#include "../gui/SDL_Extensions.h"
 #include "../../lib/spells/ISpellMechanics.h"
 
 #include "../../CCallback.h"
@@ -317,7 +318,7 @@ void BattleStacksController::showStackAmountBox(Canvas & canvas, const CStack *
 	//blitting amount
 	Point textPos = stackAnimation[stack->ID]->pos.topLeft() + amountBG->dimensions()/2 + Point(xAdd, yAdd);
 
-	canvas.drawText(textPos, EFonts::FONT_TINY, Colors::WHITE, ETextAlignment::CENTER, makeNumberShort(stack->getCount()));
+	canvas.drawText(textPos, EFonts::FONT_TINY, Colors::WHITE, ETextAlignment::CENTER, CSDL_Ext::makeNumberShort(stack->getCount()));
 }
 
 void BattleStacksController::showStack(Canvas & canvas, const CStack * stack)

+ 1 - 0
client/battle/CreatureAnimation.cpp

@@ -15,6 +15,7 @@
 
 #include "../gui/Canvas.h"
 #include "../gui/ColorFilter.h"
+#include "../gui/SDL_Extensions.h"
 
 static const SDL_Color creatureBlueBorder = { 0, 255, 255, 255 };
 static const SDL_Color creatureGoldBorder = { 255, 255, 0, 255 };

+ 10 - 15
client/gui/CAnimation.cpp

@@ -95,7 +95,7 @@ public:
 	void savePalette();
 
 	void draw(SDL_Surface * where, int posX=0, int posY=0, const Rect *src=nullptr) const override;
-	void draw(SDL_Surface * where, const SDL_Rect * dest, const SDL_Rect * src) const override;
+	void draw(SDL_Surface * where, const Rect * dest, const Rect * src) const override;
 	std::shared_ptr<IImage> scaleFast(float scale) const override;
 	void exportBitmap(const boost::filesystem::path & path) const override;
 	void playerColored(PlayerColor player) override;
@@ -651,7 +651,7 @@ void SDLImage::draw(SDL_Surface *where, int posX, int posY, const Rect *src) con
 	draw(where, &destRect, src);
 }
 
-void SDLImage::draw(SDL_Surface* where, const SDL_Rect* dest, const SDL_Rect* src) const
+void SDLImage::draw(SDL_Surface* where, const Rect * dest, const Rect* src) const
 {
 	if (!surf)
 		return;
@@ -668,28 +668,23 @@ void SDLImage::draw(SDL_Surface* where, const SDL_Rect* dest, const SDL_Rect* sr
 		if(src->y < margins.y)
 			destShift.y += margins.y - src->y;
 
-		sourceRect = Rect(*src) & Rect(margins.x, margins.y, surf->w, surf->h);
+		sourceRect = Rect(*src).intersect(Rect(margins.x, margins.y, surf->w, surf->h));
 
 		sourceRect -= margins;
 	}
 	else
 		destShift = margins;
 
-	Rect destRect(destShift.x, destShift.y, surf->w, surf->h);
-
 	if(dest)
-	{
-		destRect.x += dest->x;
-		destRect.y += dest->y;
-	}
+		destShift += dest->topLeft();
 
 	if(surf->format->BitsPerPixel == 8)
 	{
-		CSDL_Ext::blit8bppAlphaTo24bpp(surf, &sourceRect, where, &destRect);
+		CSDL_Ext::blit8bppAlphaTo24bpp(surf, sourceRect, where, destShift);
 	}
 	else
 	{
-		SDL_UpperBlit(surf, &sourceRect, where, &destRect);
+		CSDL_Ext::blitSurface(surf, sourceRect, where, destShift);
 	}
 }
 
@@ -787,7 +782,7 @@ void SDLImage::shiftPalette(int from, int howMany)
 		{
 			palette[(i+1)%howMany] = surf->format->palette->colors[from + i];
 		}
-		SDL_SetColors(surf, palette, from, howMany);
+		CSDL_Ext::setColors(surf, palette, from, howMany);
 	}
 }
 
@@ -827,7 +822,7 @@ void SDLImage::setSpecialPallete(const IImage::SpecialPalette & SpecialPalette)
 {
 	if(surf->format->palette)
 	{
-		SDL_SetColors(surf, const_cast<SDL_Color *>(SpecialPalette.data()), 1, 7);
+		CSDL_Ext::setColors(surf, const_cast<SDL_Color *>(SpecialPalette.data()), 1, 7);
 	}
 }
 
@@ -1273,7 +1268,7 @@ void CFadeAnimation::init(EMode mode, SDL_Surface * sourceSurface, bool freeSurf
 	shouldFreeSurface = freeSurfaceAtEnd;
 }
 
-void CFadeAnimation::draw(SDL_Surface * targetSurface, const SDL_Rect * sourceRect, SDL_Rect * destRect)
+void CFadeAnimation::draw(SDL_Surface * targetSurface, const Point &targetPoint)
 {
 	if (!fading || !fadingSurface || fadingMode == EMode::NONE)
 	{
@@ -1282,6 +1277,6 @@ void CFadeAnimation::draw(SDL_Surface * targetSurface, const SDL_Rect * sourceRe
 	}
 
 	CSDL_Ext::setAlpha(fadingSurface, (int)(fadingCounter * 255));
-	SDL_BlitSurface(fadingSurface, const_cast<SDL_Rect *>(sourceRect), targetSurface, destRect); //FIXME
+	CSDL_Ext::blitSurface(fadingSurface, targetSurface, targetPoint); //FIXME
 	CSDL_Ext::setAlpha(fadingSurface, 255);
 }

+ 3 - 2
client/gui/CAnimation.h

@@ -28,6 +28,7 @@ class JsonNode;
 VCMI_LIB_NAMESPACE_END
 
 struct SDL_Surface;
+struct SDL_Color;
 class CDefFile;
 class ColorFilter;
 
@@ -41,7 +42,7 @@ public:
 
 	//draws image on surface "where" at position
 	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 SDL_Rect * dest, const SDL_Rect * src) 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;
 
@@ -177,6 +178,6 @@ public:
 	~CFadeAnimation();
 	void init(EMode mode, SDL_Surface * sourceSurface, bool freeSurfaceAtEnd = false, float animDelta = DEFAULT_DELTA);
 	void update();
-	void draw(SDL_Surface * targetSurface, const SDL_Rect * sourceRect, SDL_Rect * destRect);
+	void draw(SDL_Surface * targetSurface, const Point & targetPoint);
 	bool isFading() const { return fading; }
 };

+ 316 - 0
client/gui/CCursorHandler.cpp

@@ -0,0 +1,316 @@
+/*
+ * CCursorHandler.cpp, 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
+ *
+ */
+#include "StdInc.h"
+#include "CCursorHandler.h"
+
+#include <SDL.h>
+
+#include "SDL_Extensions.h"
+#include "CGuiHandler.h"
+#include "../widgets/Images.h"
+
+#include "../CMT.h"
+
+void CCursorHandler::clearBuffer()
+{
+	CSDL_Ext::fillSurface(buffer, Colors::TRANSPARENT );
+}
+
+void CCursorHandler::updateBuffer(CIntObject * payload)
+{
+	payload->moveTo(Point(0,0));
+	payload->showAll(buffer);
+
+	needUpdate = true;
+}
+
+void CCursorHandler::replaceBuffer(CIntObject * payload)
+{
+	clearBuffer();
+	updateBuffer(payload);
+}
+
+CCursorHandler::CCursorHandler()
+	: needUpdate(true)
+	, buffer(nullptr)
+	, cursorLayer(nullptr)
+	, frameTime(0.f)
+	, showing(false)
+{
+	cursorLayer = SDL_CreateTexture(mainRenderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 40, 40);
+	SDL_SetTextureBlendMode(cursorLayer, SDL_BLENDMODE_BLEND);
+
+	xpos = ypos = 0;
+	type = Cursor::Type::DEFAULT;
+	dndObject = nullptr;
+
+	cursors =
+	{
+		std::make_unique<CAnimImage>("CRADVNTR", 0),
+		std::make_unique<CAnimImage>("CRCOMBAT", 0),
+		std::make_unique<CAnimImage>("CRDEFLT",  0),
+		std::make_unique<CAnimImage>("CRSPELL",  0)
+	};
+
+	currentCursor = cursors.at(static_cast<size_t>(Cursor::Type::DEFAULT)).get();
+
+	buffer = CSDL_Ext::newSurface(40,40);
+
+	SDL_SetSurfaceBlendMode(buffer, SDL_BLENDMODE_NONE);
+	SDL_ShowCursor(SDL_DISABLE);
+
+	set(Cursor::Map::POINTER);
+}
+
+Point CCursorHandler::position() const
+{
+	return Point(xpos, ypos);
+}
+
+void CCursorHandler::changeGraphic(Cursor::Type type, size_t index)
+{
+	assert(dndObject == nullptr);
+
+	if(type != this->type)
+	{
+		this->type = type;
+		this->frame = index;
+		currentCursor = cursors.at(static_cast<size_t>(type)).get();
+		currentCursor->setFrame(index);
+	}
+	else if(index != this->frame)
+	{
+		this->frame = index;
+		currentCursor->setFrame(index);
+	}
+
+	replaceBuffer(currentCursor);
+}
+
+void CCursorHandler::set(Cursor::Default index)
+{
+	changeGraphic(Cursor::Type::DEFAULT, static_cast<size_t>(index));
+}
+
+void CCursorHandler::set(Cursor::Map index)
+{
+	changeGraphic(Cursor::Type::ADVENTURE, static_cast<size_t>(index));
+}
+
+void CCursorHandler::set(Cursor::Combat index)
+{
+	changeGraphic(Cursor::Type::COMBAT, static_cast<size_t>(index));
+}
+
+void CCursorHandler::set(Cursor::Spellcast index)
+{
+	//Note: this is animated cursor, ignore specified frame and only change type
+	changeGraphic(Cursor::Type::SPELLBOOK, frame);
+}
+
+void CCursorHandler::dragAndDropCursor(std::unique_ptr<CAnimImage> object)
+{
+	dndObject = std::move(object);
+	if(dndObject)
+		replaceBuffer(dndObject.get());
+	else
+		replaceBuffer(currentCursor);
+}
+
+void CCursorHandler::cursorMove(const int & x, const int & y)
+{
+	xpos = x;
+	ypos = y;
+}
+
+void CCursorHandler::shiftPos( int &x, int &y )
+{
+	if(( type == Cursor::Type::COMBAT && frame != static_cast<size_t>(Cursor::Combat::POINTER)) || type == Cursor::Type::SPELLBOOK)
+	{
+		x-=16;
+		y-=16;
+
+		// Properly align the melee attack cursors.
+		if (type == Cursor::Type::COMBAT)
+		{
+			switch (static_cast<Cursor::Combat>(frame))
+			{
+			case Cursor::Combat::HIT_NORTHEAST:
+				x -= 6;
+				y += 16;
+				break;
+			case Cursor::Combat::HIT_EAST:
+				x -= 16;
+				y += 10;
+				break;
+			case Cursor::Combat::HIT_SOUTHEAST:
+				x -= 6;
+				y -= 6;
+				break;
+			case Cursor::Combat::HIT_SOUTHWEST:
+				x += 16;
+				y -= 6;
+				break;
+			case Cursor::Combat::HIT_WEST:
+				x += 16;
+				y += 11;
+				break;
+			case Cursor::Combat::HIT_NORTHWEST:
+				x += 16;
+				y += 16;
+				break;
+			case Cursor::Combat::HIT_NORTH:
+				x += 9;
+				y += 16;
+				break;
+			case Cursor::Combat::HIT_SOUTH:
+				x += 9;
+				y -= 15;
+				break;
+			}
+		}
+	}
+	else if(type == Cursor::Type::ADVENTURE)
+	{
+		if (frame == 0)
+		{
+			//no-op
+		}
+		else if(frame == 2)
+		{
+			x -= 12;
+			y -= 10;
+		}
+		else if(frame == 3)
+		{
+			x -= 12;
+			y -= 12;
+		}
+		else if(frame < 27)
+		{
+			int hlpNum = (frame - 4)%6;
+			if(hlpNum == 0)
+			{
+				x -= 15;
+				y -= 13;
+			}
+			else if(hlpNum == 1)
+			{
+				x -= 13;
+				y -= 13;
+			}
+			else if(hlpNum == 2)
+			{
+				x -= 20;
+				y -= 20;
+			}
+			else if(hlpNum == 3)
+			{
+				x -= 13;
+				y -= 16;
+			}
+			else if(hlpNum == 4)
+			{
+				x -= 8;
+				y -= 9;
+			}
+			else if(hlpNum == 5)
+			{
+				x -= 14;
+				y -= 16;
+			}
+		}
+		else if(frame == 41)
+		{
+			x -= 14;
+			y -= 16;
+		}
+		else if(frame < 31 || frame == 42)
+		{
+			x -= 20;
+			y -= 20;
+		}
+	}
+}
+
+void CCursorHandler::centerCursor()
+{
+	this->xpos = static_cast<int>((screen->w / 2.) - (currentCursor->pos.w / 2.));
+	this->ypos = static_cast<int>((screen->h / 2.) - (currentCursor->pos.h / 2.));
+	SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
+	CSDL_Ext::warpMouse(this->xpos, this->ypos);
+	SDL_EventState(SDL_MOUSEMOTION, SDL_ENABLE);
+}
+
+void CCursorHandler::render()
+{
+	if(!showing)
+		return;
+
+	if (type == Cursor::Type::SPELLBOOK)
+	{
+		static const float frameDisplayDuration = 0.1f;
+
+		frameTime += GH.mainFPSmng->getElapsedMilliseconds() / 1000.f;
+		size_t newFrame = frame;
+
+		while (frameTime > frameDisplayDuration)
+		{
+			frameTime -= frameDisplayDuration;
+			newFrame++;
+		}
+
+		auto & animation = cursors.at(static_cast<size_t>(type));
+
+		while (newFrame > animation->size())
+			newFrame -= animation->size();
+
+		changeGraphic(Cursor::Type::SPELLBOOK, newFrame);
+	}
+
+	//the must update texture in the main (renderer) thread, but changes to cursor type may come from other threads
+	updateTexture();
+
+	int x = xpos;
+	int y = ypos;
+	shiftPos(x, y);
+
+	if(dndObject)
+	{
+		x -= dndObject->pos.w/2;
+		y -= dndObject->pos.h/2;
+	}
+
+	SDL_Rect destRect;
+	destRect.x = x;
+	destRect.y = y;
+	destRect.w = 40;
+	destRect.h = 40;
+
+	SDL_RenderCopy(mainRenderer, cursorLayer, nullptr, &destRect);
+}
+
+void CCursorHandler::updateTexture()
+{
+	if(needUpdate)
+	{
+		SDL_UpdateTexture(cursorLayer, nullptr, buffer->pixels, buffer->pitch);
+		needUpdate = false;
+	}
+}
+
+CCursorHandler::~CCursorHandler()
+{
+	if(buffer)
+		SDL_FreeSurface(buffer);
+
+	if(cursorLayer)
+		SDL_DestroyTexture(cursorLayer);
+}

+ 8 - 7
client/gui/CGuiHandler.cpp

@@ -15,6 +15,7 @@
 
 #include "CIntObject.h"
 #include "CursorHandler.h"
+#include "SDL_Extensions.h"
 
 #include "../CGameInfo.h"
 #include "../../lib/CThreadHelper.h"
@@ -167,7 +168,7 @@ void CGuiHandler::totalRedraw()
 #endif
 	for(auto & elem : objsToBlit)
 		elem->showAll(screen2);
-	blitAt(screen2,0,0,screen);
+	CSDL_Ext::blitAt(screen2,0,0,screen);
 }
 
 void CGuiHandler::updateTime()
@@ -289,7 +290,7 @@ void CGuiHandler::handleCurrentEvent()
 				for(auto i = hlp.begin(); i != hlp.end() && continueEventHandling; i++)
 				{
 					if(!vstd::contains(doubleClickInterested, *i)) continue;
-					if(isItIn(&(*i)->pos, current->motion.x, current->motion.y))
+					if((*i)->pos.isInside(current->motion.x, current->motion.y))
 					{
 						(*i)->onDoubleClick();
 					}
@@ -321,7 +322,7 @@ void CGuiHandler::handleCurrentEvent()
 			// SDL doesn't have the proper values for mouse positions on SDL_MOUSEWHEEL, refetch them
 			int x = 0, y = 0;
 			SDL_GetMouseState(&x, &y);
-			(*i)->wheelScrolled(current->wheel.y < 0, isItIn(&(*i)->pos, x, y));
+			(*i)->wheelScrolled(current->wheel.y < 0, (*i)->pos.isInside(x, y));
 		}
 	}
 	else if(current->type == SDL_TEXTINPUT)
@@ -367,7 +368,7 @@ void CGuiHandler::handleMouseButtonClick(CIntObjectList & interestedObjs, EIntOb
 		auto prev = (*i)->mouseState(btn);
 		if(!isPressed)
 			(*i)->updateMouseState(btn, isPressed);
-		if(isItIn(&(*i)->pos, current->motion.x, current->motion.y))
+		if((*i)->pos.isInside(current->motion.x, current->motion.y))
 		{
 			if(isPressed)
 				(*i)->updateMouseState(btn, isPressed);
@@ -384,7 +385,7 @@ void CGuiHandler::handleMouseMotion()
 	std::vector<CIntObject*> hlp;
 	for(auto & elem : hoverable)
 	{
-		if(isItIn(&(elem)->pos, current->motion.x, current->motion.y))
+		if(elem->pos.isInside(current->motion.x, current->motion.y))
 		{
 			if (!(elem)->hovered)
 				hlp.push_back((elem));
@@ -408,7 +409,7 @@ void CGuiHandler::simpleRedraw()
 {
 	//update only top interface and draw background
 	if(objsToBlit.size() > 1)
-		blitAt(screen2,0,0,screen); //blit background
+		CSDL_Ext::blitAt(screen2,0,0,screen); //blit background
 	if(!objsToBlit.empty())
 		objsToBlit.back()->show(screen); //blit active interface/window
 }
@@ -419,7 +420,7 @@ void CGuiHandler::handleMoveInterested(const SDL_MouseMotionEvent & motion)
 	std::list<CIntObject*> miCopy = motioninterested;
 	for(auto & elem : miCopy)
 	{
-		if(elem->strongInterest || isItInOrLowerBounds(&elem->pos, motion.x, motion.y)) //checking lower bounds fixes bug #2476
+		if(elem->strongInterest || Rect::createAround(elem->pos, 1).isInside( motion.x, motion.y)) //checking bounds including border fixes bug #2476
 		{
 			(elem)->mouseMoved(motion);
 		}

+ 4 - 2
client/gui/CGuiHandler.h

@@ -9,9 +9,9 @@
  */
 #pragma once
 
-//#include "../../lib/CStopWatch.h"
 #include "Geometries.h"
-#include "SDL_Extensions.h"
+
+#include <SDL_events.h>
 
 VCMI_LIB_NAMESPACE_BEGIN
 
@@ -19,6 +19,8 @@ template <typename T> struct CondSh;
 
 VCMI_LIB_NAMESPACE_END
 
+union SDL_Event;
+
 class CFramerateManager;
 class IStatusBar;
 class CIntObject;

+ 3 - 11
client/gui/CIntObject.cpp

@@ -14,6 +14,8 @@
 #include "SDL_Extensions.h"
 #include "../CMessage.h"
 
+#include <SDL_pixels.h>
+
 IShowActivatable::IShowActivatable()
 {
 	type = 0;
@@ -176,7 +178,7 @@ void CIntObject::printAtMiddleLoc(const std::string & text, const Point &p, EFon
 
 void CIntObject::blitAtLoc( SDL_Surface * src, int x, int y, SDL_Surface * dst )
 {
-	blitAt(src, pos.x + x, pos.y + y, dst);
+	CSDL_Ext::blitAt(src, pos.x + x, pos.y + y, dst);
 }
 
 void CIntObject::blitAtLoc(SDL_Surface * src, const Point &p, SDL_Surface * dst)
@@ -219,16 +221,6 @@ void CIntObject::enable()
 	recActions = 255;
 }
 
-bool CIntObject::isItInLoc( const SDL_Rect &rect, int x, int y )
-{
-	return isItIn(&rect, x - pos.x, y - pos.y);
-}
-
-bool CIntObject::isItInLoc( const SDL_Rect &rect, const Point &p )
-{
-	return isItIn(&rect, p.x - pos.x, p.y - pos.y);
-}
-
 void CIntObject::fitToScreen(int borderWidth, bool propagate)
 {
 	Point newPos = pos.topLeft();

+ 2 - 3
client/gui/CIntObject.h

@@ -9,7 +9,6 @@
  */
 #pragma once
 
-#include <SDL_events.h>
 #include "Geometries.h"
 #include "../Graphics.h"
 
@@ -18,6 +17,8 @@ class CGuiHandler;
 class CPicture;
 
 struct SDL_KeyboardEvent;
+struct SDL_TextInputEvent;
+struct SDL_TextEditingEvent;
 
 using boost::logic::tribool;
 
@@ -165,8 +166,6 @@ public:
 	//request complete redraw of this object
 	void redraw() override;
 
-	bool isItInLoc(const SDL_Rect &rect, int x, int y);
-	bool isItInLoc(const SDL_Rect &rect, const Point &p);
 	const Rect & center(const Rect &r, bool propagate = true); //sets pos so that r will be in the center of screen, assigns sizes of r to pos, returns new position
 	const Rect & center(const Point &p, bool propagate = true);  //moves object so that point p will be in its center
 	const Rect & center(bool propagate = true); //centers when pos.w and pos.h are set, returns new position

+ 6 - 4
client/gui/Canvas.cpp

@@ -16,6 +16,8 @@
 
 #include "../Graphics.h"
 
+#include <SDL_surface.h>
+
 Canvas::Canvas(SDL_Surface * surface):
 	surface(surface),
 	renderOffset(0,0)
@@ -34,10 +36,10 @@ Canvas::Canvas(Canvas & other, const Rect & newClipRect):
 	Canvas(other)
 {
 	clipRect.emplace();
-	SDL_GetClipRect(surface, clipRect.get_ptr());
+	CSDL_Ext::getClipRect(surface, clipRect.get());
 
 	Rect currClipRect = newClipRect + renderOffset;
-	SDL_SetClipRect(surface, &currClipRect);
+	CSDL_Ext::setClipRect(surface, currClipRect);
 
 	renderOffset += newClipRect.topLeft();
 }
@@ -51,7 +53,7 @@ Canvas::Canvas(const Point & size):
 Canvas::~Canvas()
 {
 	if (clipRect)
-		SDL_SetClipRect(surface, clipRect.get_ptr());
+		CSDL_Ext::setClipRect(surface, clipRect.get());
 
 	SDL_FreeSurface(surface);
 }
@@ -72,7 +74,7 @@ void Canvas::draw(std::shared_ptr<IImage> image, const Point & pos, const Rect &
 
 void Canvas::draw(Canvas & image, const Point & pos)
 {
-	blitAt(image.surface, renderOffset.x + pos.x, renderOffset.y + pos.y, surface);
+	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)

+ 1 - 1
client/gui/ColorFilter.cpp

@@ -10,7 +10,7 @@
 #include "StdInc.h"
 #include "ColorFilter.h"
 
-#include <SDL2/SDL_pixels.h>
+#include <SDL_pixels.h>
 
 #include "../../lib/JsonNode.h"
 

+ 3 - 5
client/gui/CursorHandler.cpp

@@ -250,7 +250,7 @@ void CursorHandler::centerCursor()
 	pos = screenSize / 2 - getPivotOffset();
 
 	SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
-	SDL_WarpMouse(pos.x, pos.y);
+	CSDL_Ext::warpMouse(pos.x, pos.y);
 	SDL_EventState(SDL_MOUSEMOTION, SDL_ENABLE);
 
 	cursor->setCursorPosition(pos);
@@ -345,8 +345,7 @@ void CursorSoftware::updateTexture()
 	if (!cursorSurface ||  Point(cursorSurface->w, cursorSurface->h) != cursorImage->dimensions())
 		createTexture(cursorImage->dimensions());
 
-	Uint32 fillColor = SDL_MapRGBA(cursorSurface->format, 0, 0, 0, 0);
-	CSDL_Ext::fillRect(cursorSurface, nullptr, fillColor);
+	CSDL_Ext::fillSurface(cursorSurface, Colors::TRANSPARENT);
 
 	cursorImage->draw(cursorSurface);
 	SDL_UpdateTexture(cursorTexture, NULL, cursorSurface->pixels, cursorSurface->pitch);
@@ -414,8 +413,7 @@ void CursorHardware::setImage(std::shared_ptr<IImage> image, const Point & pivot
 {
 	auto cursorSurface = CSDL_Ext::newSurface(image->dimensions().x, image->dimensions().y);
 
-	Uint32 fillColor = SDL_MapRGBA(cursorSurface->format, 0, 0, 0, 0);
-	CSDL_Ext::fillRect(cursorSurface, nullptr, fillColor);
+	CSDL_Ext::fillSurface(cursorSurface, Colors::TRANSPARENT);
 
 	image->draw(cursorSurface);
 

+ 6 - 7
client/gui/Fonts.cpp

@@ -130,11 +130,11 @@ size_t CBitmapFont::getGlyphWidth(const char * data) const
 void CBitmapFont::renderCharacter(SDL_Surface * surface, const BitmapChar & character, const SDL_Color & color, int &posX, int &posY) const
 {
 	Rect clipRect;
-	SDL_GetClipRect(surface, &clipRect);
+	CSDL_Ext::getClipRect(surface, clipRect);
 
 	posX += character.leftOffset;
 
-	TColorPutter colorPutter = CSDL_Ext::getPutterFor(surface, 0);
+	CSDL_Ext::TColorPutter colorPutter = CSDL_Ext::getPutterFor(surface, 0);
 
 	Uint8 bpp = surface->format->BytesPerPixel;
 
@@ -270,7 +270,7 @@ void CTrueTypeFont::renderText(SDL_Surface * surface, const std::string & data,
 	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, Point(pos.x + 1, pos.y + 1));
+		renderText(surface, data, black, pos + Point(1,1));
 	}
 
 	if (!data.empty())
@@ -283,8 +283,7 @@ void CTrueTypeFont::renderText(SDL_Surface * surface, const std::string & data,
 
 		assert(rendered);
 
-		Rect rect(pos.x, pos.y, rendered->w, rendered->h);
-		SDL_BlitSurface(rendered, nullptr, surface, &rect);
+		CSDL_Ext::blitSurface(rendered, surface, pos);
 		SDL_FreeSurface(rendered);
 	}
 }
@@ -308,9 +307,9 @@ void CBitmapHanFont::renderCharacter(SDL_Surface * surface, int characterIndex,
 {
 	//TODO: somewhat duplicated with CBitmapFont::renderCharacter();
 	Rect clipRect;
-	SDL_GetClipRect(surface, &clipRect);
+	CSDL_Ext::getClipRect(surface, clipRect);
 
-	TColorPutter colorPutter = CSDL_Ext::getPutterFor(surface, 0);
+	CSDL_Ext::TColorPutter colorPutter = CSDL_Ext::getPutterFor(surface, 0);
 	Uint8 bpp = surface->format->BytesPerPixel;
 
 	// start of line, may differ from 0 due to end of surface or clipped surface

+ 1 - 1
client/gui/Fonts.h

@@ -15,7 +15,7 @@ class JsonNode;
 
 VCMI_LIB_NAMESPACE_END
 
-struct Point;
+class Point;
 struct SDL_Surface;
 struct SDL_Color;
 

+ 3 - 2
client/gui/NotificationHandler.h

@@ -10,7 +10,8 @@
 
 #pragma once
 
-#include <SDL_events.h>
+struct SDL_Window;
+union SDL_Event;
 
 class NotificationHandler
 {
@@ -19,4 +20,4 @@ public:
 	static void init(SDL_Window * window);
 	static bool handleSdlEvent(const SDL_Event & ev);
 	static void destroy();
-};
+};

+ 136 - 93
client/gui/SDL_Extensions.cpp

@@ -16,6 +16,11 @@
 #include "../Graphics.h"
 #include "../CMT.h"
 
+#include <SDL_version.h>
+#include <SDL_render.h>
+#include <SDL_video.h>
+#include <SDL_events.h>
+
 #ifdef VCMI_APPLE
 #include <dispatch/dispatch.h>
 #endif
@@ -24,18 +29,52 @@
 #include "ios/utils.h"
 #endif
 
-const SDL_Color Colors::YELLOW = { 229, 215, 123, 0 };
-const SDL_Color Colors::WHITE = { 255, 243, 222, 0 };
-const SDL_Color Colors::METALLIC_GOLD = { 173, 142, 66, 0 };
-const SDL_Color Colors::GREEN = { 0, 255, 0, 0 };
-const SDL_Color Colors::ORANGE = { 232, 184, 32, 0 };
-const SDL_Color Colors::BRIGHT_YELLOW = { 242, 226, 110, 0 };
-const SDL_Color Colors::DEFAULT_KEY_COLOR = {0, 255, 255, 0};
+const SDL_Color Colors::YELLOW = { 229, 215, 123, SDL_ALPHA_OPAQUE };
+const SDL_Color Colors::WHITE = { 255, 243, 222, SDL_ALPHA_OPAQUE };
+const SDL_Color Colors::METALLIC_GOLD = { 173, 142, 66, SDL_ALPHA_OPAQUE };
+const SDL_Color Colors::GREEN = { 0, 255, 0, SDL_ALPHA_OPAQUE };
+const SDL_Color Colors::ORANGE = { 232, 184, 32, SDL_ALPHA_OPAQUE };
+const SDL_Color Colors::BRIGHT_YELLOW = { 242, 226, 110, SDL_ALPHA_OPAQUE };
+const SDL_Color Colors::DEFAULT_KEY_COLOR = {0, 255, 255, SDL_ALPHA_OPAQUE};
+const SDL_Color Colors::RED = {255, 0, 0, SDL_ALPHA_OPAQUE};
+const SDL_Color Colors::PURPLE = {255, 75, 125, SDL_ALPHA_OPAQUE};
+const SDL_Color Colors::BLACK = {0, 0, 0, SDL_ALPHA_OPAQUE};
+const SDL_Color Colors::TRANSPARENT = {0, 0, 0, SDL_ALPHA_TRANSPARENT};
+
+void CSDL_Ext::setColors(SDL_Surface *surface, SDL_Color *colors, int firstcolor, int ncolors)
+{
+	SDL_SetPaletteColors(surface->format->palette,colors,firstcolor,ncolors);
+}
+
+void CSDL_Ext::warpMouse(int x, int y)
+{
+	SDL_WarpMouseInWindow(mainWindow,x,y);
+}
+
+bool CSDL_Ext::isCtrlKeyDown()
+{
+	return SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_LCTRL] || SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_RCTRL];
+}
+
+bool CSDL_Ext::isAltKeyDown()
+{
+	return SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_LALT] || SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_RALT];
+}
+
+bool CSDL_Ext::isShiftKeyDown()
+{
+	return SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_LSHIFT] || SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_RSHIFT];
+}
+
+void CSDL_Ext::setAlpha(SDL_Surface * bg, int value)
+{
+	SDL_SetSurfaceAlphaMod(bg, value);
+}
 
-void SDL_UpdateRect(SDL_Surface *surface, int x, int y, int w, int h)
+void CSDL_Ext::updateRect(SDL_Surface *surface, const Rect & rect )
 {
-	Rect rect(x,y,w,h);
-	if(0 !=SDL_UpdateTexture(screenTexture, &rect, surface->pixels, surface->pitch))
+	SDL_Rect rectSDL = Geometry::toSDL(rect);
+	if(0 !=SDL_UpdateTexture(screenTexture, &rectSDL, surface->pixels, surface->pitch))
 		logGlobal->error("%sSDL_UpdateTexture %s", __FUNCTION__, SDL_GetError());
 
 	SDL_RenderClear(mainRenderer);
@@ -76,24 +115,14 @@ SDL_Surface * CSDL_Ext::createSurfaceWithBpp(int width, int height)
 	return SDL_CreateRGBSurface(0, width, height, bpp * 8, rMask, gMask, bMask, aMask);
 }
 
-bool isItIn(const SDL_Rect * rect, int x, int y)
+void CSDL_Ext::blitAt(SDL_Surface * src, int x, int y, SDL_Surface * dst)
 {
-	return (x>rect->x && x<rect->x+rect->w) && (y>rect->y && y<rect->y+rect->h);
+	if(!dst)
+		dst = screen;
+	CSDL_Ext::blitSurface(src, dst, Point(x, y));
 }
 
-bool isItInOrLowerBounds(const SDL_Rect * rect, int x, int y)
-{
-	return (x >= rect->x && x < rect->x + rect->w) && (y >= rect->y && y < rect->y + rect->h);
-}
-
-void blitAt(SDL_Surface * src, int x, int y, SDL_Surface * dst)
-{
-	if(!dst) dst = screen;
-	SDL_Rect pom = genRect(src->h,src->w,x,y);
-	CSDL_Ext::blitSurface(src,nullptr,dst,&pom);
-}
-
-void blitAt(SDL_Surface * src, const SDL_Rect & pos, SDL_Surface * dst)
+void CSDL_Ext::blitAt(SDL_Surface * src, const Rect & pos, SDL_Surface * dst)
 {
 	if (src)
 		blitAt(src,pos.x,pos.y,dst);
@@ -160,7 +189,7 @@ SDL_Surface * CSDL_Ext::horizontalFlip(SDL_Surface * toRot)
 	return ret;
 }
 
-Uint32 CSDL_Ext::SDL_GetPixel(SDL_Surface *surface, const int & x, const int & y, bool colorByte)
+Uint32 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 */
@@ -189,8 +218,14 @@ Uint32 CSDL_Ext::SDL_GetPixel(SDL_Surface *surface, const int & x, const int & y
 }
 
 template<int bpp>
-int CSDL_Ext::blit8bppAlphaTo24bppT(const SDL_Surface * src, const SDL_Rect * srcRect, SDL_Surface * dst, SDL_Rect * dstRect)
+int CSDL_Ext::blit8bppAlphaTo24bppT(const SDL_Surface * src, const Rect & srcRectInput, SDL_Surface * dst, const Point & dstPointInput)
 {
+	SDL_Rect srcRectInstance = Geometry::toSDL(srcRectInput);
+	SDL_Rect dstRectInstance = Geometry::toSDL(Rect(dstPointInput, srcRectInput.dimensions()));
+
+	SDL_Rect * srcRect =&srcRectInstance;
+	SDL_Rect * dstRect =&dstRectInstance;
+
 	/* Make sure the surfaces aren't locked */
 	if ( ! src || ! dst )
 	{
@@ -310,13 +345,13 @@ int CSDL_Ext::blit8bppAlphaTo24bppT(const SDL_Surface * src, const SDL_Rect * sr
 	return 0;
 }
 
-int CSDL_Ext::blit8bppAlphaTo24bpp(const SDL_Surface * src, const SDL_Rect * srcRect, SDL_Surface * dst, SDL_Rect * dstRect)
+int CSDL_Ext::blit8bppAlphaTo24bpp(const SDL_Surface * src, const Rect & srcRect, SDL_Surface * dst, const Point & dstPoint)
 {
 	switch(dst->format->BytesPerPixel)
 	{
-	case 2: return blit8bppAlphaTo24bppT<2>(src, srcRect, dst, dstRect);
-	case 3: return blit8bppAlphaTo24bppT<3>(src, srcRect, dst, dstRect);
-	case 4: return blit8bppAlphaTo24bppT<4>(src, srcRect, dst, dstRect);
+	case 2: return blit8bppAlphaTo24bppT<2>(src, srcRect, dst, dstPoint);
+	case 3: return blit8bppAlphaTo24bppT<3>(src, srcRect, dst, dstPoint);
+	case 4: return blit8bppAlphaTo24bppT<4>(src, srcRect, dst, dstPoint);
 	default:
 		logGlobal->error("%d bpp is not supported!", (int)dst->format->BitsPerPixel);
 		return -1;
@@ -406,26 +441,26 @@ void CSDL_Ext::drawLine(SDL_Surface * sur, int x1, int y1, int x2, int y2, const
 	}
 }
 
-void CSDL_Ext::drawBorder(SDL_Surface * sur, int x, int y, int w, int h, const int3 &color)
+void CSDL_Ext::drawBorder(SDL_Surface * sur, int x, int y, int w, int h, const SDL_Color &color)
 {
 	for(int i = 0; i < w; i++)
 	{
-		SDL_PutPixelWithoutRefreshIfInSurf(sur,x+i,y,color.x,color.y,color.z);
-		SDL_PutPixelWithoutRefreshIfInSurf(sur,x+i,y+h-1,color.x,color.y,color.z);
+		CSDL_Ext::putPixelWithoutRefreshIfInSurf(sur,x+i,y,color.r,color.g,color.b);
+		CSDL_Ext::putPixelWithoutRefreshIfInSurf(sur,x+i,y+h-1,color.r,color.g,color.b);
 	}
 	for(int i = 0; i < h; i++)
 	{
-		SDL_PutPixelWithoutRefreshIfInSurf(sur,x,y+i,color.x,color.y,color.z);
-		SDL_PutPixelWithoutRefreshIfInSurf(sur,x+w-1,y+i,color.x,color.y,color.z);
+		CSDL_Ext::putPixelWithoutRefreshIfInSurf(sur,x,y+i,color.r,color.g,color.b);
+		CSDL_Ext::putPixelWithoutRefreshIfInSurf(sur,x+w-1,y+i,color.r,color.g,color.b);
 	}
 }
 
-void CSDL_Ext::drawBorder( SDL_Surface * sur, const SDL_Rect &r, const int3 &color )
+void CSDL_Ext::drawBorder( SDL_Surface * sur, const Rect &r, const SDL_Color &color )
 {
 	drawBorder(sur, r.x, r.y, r.w, r.h, color);
 }
 
-void CSDL_Ext::drawDashedBorder(SDL_Surface * sur, const Rect &r, const int3 &color)
+void CSDL_Ext::drawDashedBorder(SDL_Surface * sur, const Rect &r, const SDL_Color &color)
 {
 	const int y1 = r.y, y2 = r.y + r.h-1;
 	for (int i=0; i<r.w; i++)
@@ -433,8 +468,8 @@ void CSDL_Ext::drawDashedBorder(SDL_Surface * sur, const Rect &r, const int3 &co
 		const int x = r.x + i;
 		if (i%4 || (i==0))
 		{
-			SDL_PutPixelWithoutRefreshIfInSurf(sur, x, y1, color.x, color.y, color.z);
-			SDL_PutPixelWithoutRefreshIfInSurf(sur, x, y2, color.x, color.y, color.z);
+			CSDL_Ext::putPixelWithoutRefreshIfInSurf(sur, x, y1, color.r, color.g, color.b);
+			CSDL_Ext::putPixelWithoutRefreshIfInSurf(sur, x, y2, color.r, color.g, color.b);
 		}
 	}
 
@@ -444,8 +479,8 @@ void CSDL_Ext::drawDashedBorder(SDL_Surface * sur, const Rect &r, const int3 &co
 		const int y = r.y + i;
 		if ((i%4) || (i==0))
 		{
-			SDL_PutPixelWithoutRefreshIfInSurf(sur, x1, y, color.x, color.y, color.z);
-			SDL_PutPixelWithoutRefreshIfInSurf(sur, x2, y, color.x, color.y, color.z);
+			CSDL_Ext::putPixelWithoutRefreshIfInSurf(sur, x1, y, color.r, color.g, color.b);
+			CSDL_Ext::putPixelWithoutRefreshIfInSurf(sur, x2, y, color.r, color.g, color.b);
 		}
 	}
 }
@@ -459,13 +494,13 @@ void CSDL_Ext::setPlayerColor(SDL_Surface * sur, PlayerColor player)
 		SDL_Color *color = (player == PlayerColor::NEUTRAL
 							? graphics->neutralColor
 							: &graphics->playerColors[player.getNum()]);
-		SDL_SetColors(sur, color, 5, 1);
+		CSDL_Ext::setColors(sur, color, 5, 1);
 	}
 	else
 		logGlobal->warn("Warning, setPlayerColor called on not 8bpp surface!");
 }
 
-TColorPutter CSDL_Ext::getPutterFor(SDL_Surface * const &dest, int incrementing)
+CSDL_Ext::TColorPutter CSDL_Ext::getPutterFor(SDL_Surface * const &dest, int incrementing)
 {
 #define CASE_BPP(BytesPerPixel)							\
 case BytesPerPixel:									\
@@ -489,7 +524,7 @@ case BytesPerPixel:									\
 
 }
 
-TColorPutterAlpha CSDL_Ext::getPutterAlphaFor(SDL_Surface * const &dest, int incrementing)
+CSDL_Ext::TColorPutterAlpha CSDL_Ext::getPutterAlphaFor(SDL_Surface * const &dest, int incrementing)
 {
 	switch(dest->format->BytesPerPixel)
 	{
@@ -524,7 +559,7 @@ bool CSDL_Ext::isTransparent( SDL_Surface * srf, int x, int y )
 
 	SDL_Color color;
 
-	SDL_GetRGBA(SDL_GetPixel(srf, x, y), srf->format, &color.r, &color.g, &color.b, &color.a);
+	SDL_GetRGBA(CSDL_Ext::getPixel(srf, x, y), srf->format, &color.r, &color.g, &color.b, &color.a);
 
 	bool pixelTransparent = color.a < 128;
 	bool pixelCyan = (color.r == 0 && color.g == 255 && color.b == 255);
@@ -548,7 +583,7 @@ void CSDL_Ext::VflipSurf(SDL_Surface * surf)
 	}
 }
 
-void CSDL_Ext::SDL_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 & R, const Uint8 & G, const Uint8 & B, Uint8 A)
 {
 	Uint8 *p = getPxPtr(ekran, x, y);
 	getPutterFor(ekran, false)(p, R, G, B);
@@ -561,17 +596,17 @@ void CSDL_Ext::SDL_PutPixelWithoutRefresh(SDL_Surface *ekran, const int & x, con
 	}
 }
 
-void CSDL_Ext::SDL_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 & R, const Uint8 & G, const Uint8 & B, Uint8 A)
 {
 	const SDL_Rect & rect = ekran->clip_rect;
 
 	if(x >= rect.x  &&  x < rect.w + rect.x
 	&& y >= rect.y  &&  y < rect.h + rect.y)
-		SDL_PutPixelWithoutRefresh(ekran, x, y, R, G, B, A);
+		CSDL_Ext::putPixelWithoutRefresh(ekran, x, y, R, G, B, A);
 }
 
 template<int bpp>
-void CSDL_Ext::applyEffectBpp( SDL_Surface * surf, const SDL_Rect * rect, int mode )
+void CSDL_Ext::applyEffectBpp(SDL_Surface * surf, const Rect & rect, int mode )
 {
 	switch(mode)
 	{
@@ -580,9 +615,9 @@ void CSDL_Ext::applyEffectBpp( SDL_Surface * surf, const SDL_Rect * rect, int mo
 			const int sepiaDepth = 20;
 			const int sepiaIntensity = 30;
 
-			for(int xp = rect->x; xp < rect->x + rect->w; ++xp)
+			for(int xp = rect.x; xp < rect.x + rect.w; ++xp)
 			{
-				for(int yp = rect->y; yp < rect->y + rect->h; ++yp)
+				for(int yp = rect.y; yp < rect.y + rect.h; ++yp)
 				{
 					Uint8 * pixel = (ui8*)surf->pixels + yp * surf->pitch + xp * surf->format->BytesPerPixel;
 					int r = Channels::px<bpp>::r.get(pixel);
@@ -613,9 +648,9 @@ void CSDL_Ext::applyEffectBpp( SDL_Surface * surf, const SDL_Rect * rect, int mo
 		break;
 	case 1: //grayscale
 		{
-			for(int xp = rect->x; xp < rect->x + rect->w; ++xp)
+			for(int xp = rect.x; xp < rect.x + rect.w; ++xp)
 			{
-				for(int yp = rect->y; yp < rect->y + rect->h; ++yp)
+				for(int yp = rect.y; yp < rect.y + rect.h; ++yp)
 				{
 					Uint8 * pixel = (ui8*)surf->pixels + yp * surf->pitch + xp * surf->format->BytesPerPixel;
 
@@ -638,7 +673,7 @@ void CSDL_Ext::applyEffectBpp( SDL_Surface * surf, const SDL_Rect * rect, int mo
 	}
 }
 
-void CSDL_Ext::applyEffect( SDL_Surface * surf, const SDL_Rect * rect, int mode )
+void CSDL_Ext::applyEffect( SDL_Surface * surf, const Rect & rect, int mode )
 {
 	switch(surf->format->BytesPerPixel)
 	{
@@ -766,46 +801,34 @@ SDL_Surface * CSDL_Ext::scaleSurface(SDL_Surface *surf, int width, int height)
 	return ret;
 }
 
-void CSDL_Ext::blitSurface( SDL_Surface * src, const SDL_Rect * srcRect, SDL_Surface * dst, SDL_Rect * dstRect )
+void CSDL_Ext::blitSurface(SDL_Surface * src, const Rect & srcRectInput, SDL_Surface * dst, const Point & dstPoint)
 {
-	if (dst != screen)
-	{
-		SDL_UpperBlit(src, srcRect, dst, dstRect);
-	}
-	else
-	{
-		SDL_Rect betterDst;
-		if (dstRect)
-		{
-			betterDst = *dstRect;
-		}
-		else
-		{
-			betterDst = Rect(0, 0, dst->w, dst->h);
-		}
+	SDL_Rect srcRect = Geometry::toSDL(srcRectInput);
+	SDL_Rect dstRect = Geometry::toSDL(Rect(dstPoint, srcRectInput.dimensions()));
 
-		SDL_UpperBlit(src, srcRect, dst, &betterDst);
-	}
+	SDL_UpperBlit(src, &srcRect, dst, &dstRect);
 }
 
-void CSDL_Ext::fillRect( SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color )
+void CSDL_Ext::blitSurface(SDL_Surface * src, SDL_Surface * dst, const Point & dest)
 {
-	SDL_Rect newRect;
-	if (dstrect)
-	{
-		newRect = *dstrect;
-	}
-	else
-	{
-		newRect = Rect(0, 0, dst->w, dst->h);
-	}
-	SDL_FillRect(dst, &newRect, color);
+	Rect allSurface( Point(0,0), Point(src->w, src->h));
+
+	blitSurface(src, allSurface, dst, dest);
+}
+
+void CSDL_Ext::fillSurface( SDL_Surface *dst, const SDL_Color & color )
+{
+	Rect allSurface( Point(0,0), Point(dst->w, dst->h));
+
+	fillRect(dst, allSurface, color);
 }
 
-void CSDL_Ext::fillRectBlack( SDL_Surface *dst, SDL_Rect *dstrect)
+void CSDL_Ext::fillRect( SDL_Surface *dst, const Rect & dstrect, const SDL_Color & color )
 {
-	const Uint32 black = SDL_MapRGB(dst->format,0,0,0);
-	fillRect(dst,dstrect,black);
+	SDL_Rect newRect = Geometry::toSDL(dstrect);
+
+	uint32_t sdlColor = SDL_MapRGBA(dst->format, color.r, color.g, color.b, color.a);
+	SDL_FillRect(dst, &newRect, sdlColor);
 }
 
 void CSDL_Ext::fillTexture(SDL_Surface *dst, SDL_Surface * src)
@@ -822,7 +845,7 @@ void CSDL_Ext::fillTexture(SDL_Surface *dst, SDL_Surface * src)
 		{
 			int xLeft = std::min<int>(srcRect.w, dstRect.x + dstRect.w - x);
 			int yLeft = std::min<int>(srcRect.h, dstRect.y + dstRect.h - y);
-			Rect currentDest(x, y, xLeft, yLeft);
+			SDL_Rect currentDest{x, y, xLeft, yLeft};
 			SDL_BlitSurface(src, &srcRect, dst, &currentDest);
 		}
 	}
@@ -834,15 +857,17 @@ SDL_Color CSDL_Ext::makeColor(ui8 r, ui8 g, ui8 b, ui8 a)
 	return ret;
 }
 
-void CSDL_Ext::startTextInput(SDL_Rect * where)
+void CSDL_Ext::startTextInput(const Rect & whereInput)
 {
-	auto impl = [](SDL_Rect * where)
+	SDL_Rect where = Geometry::toSDL(whereInput);
+
+	auto impl = [](SDL_Rect & where)
 	{
 		if (SDL_IsTextInputActive() == SDL_FALSE)
 		{
 			SDL_StartTextInput();
 		}
-		SDL_SetTextInputRect(where);
+		SDL_SetTextInputRect(&where);
 	};
 
 #ifdef VCMI_APPLE
@@ -858,12 +883,12 @@ void CSDL_Ext::startTextInput(SDL_Rect * where)
 	SDL_RenderGetViewport(renderer, &viewport);
 
 	const auto nativeScale = iOS_utils::screenScale();
-	auto rectInScreenCoordinates = *where;
+	auto rectInScreenCoordinates = where;
 	rectInScreenCoordinates.x = (viewport.x + rectInScreenCoordinates.x) * scaleX / nativeScale;
 	rectInScreenCoordinates.y = (viewport.y + rectInScreenCoordinates.y) * scaleY / nativeScale;
 	rectInScreenCoordinates.w = rectInScreenCoordinates.w * scaleX / nativeScale;
 	rectInScreenCoordinates.h = rectInScreenCoordinates.h * scaleY / nativeScale;
-	impl(&rectInScreenCoordinates);
+	impl(rectInScreenCoordinates);
 #else
 	impl(where);
 #endif
@@ -918,7 +943,25 @@ void CSDL_Ext::setDefaultColorKeyPresize(SDL_Surface * surface)
 	}
 }
 
+void CSDL_Ext::setClipRect(SDL_Surface * src, const Rect & other)
+{
+	SDL_Rect rect = Geometry::toSDL(other);
+
+	SDL_SetClipRect(src, &rect);
+}
+
+void CSDL_Ext::getClipRect(SDL_Surface * src, Rect & other)
+{
+	SDL_Rect rect;
+
+	SDL_GetClipRect(src, &rect);
+
+	other = Geometry::fromSDL(rect);
+}
+
+
 
 template SDL_Surface * CSDL_Ext::createSurfaceWithBpp<2>(int, int);
 template SDL_Surface * CSDL_Ext::createSurfaceWithBpp<3>(int, int);
 template SDL_Surface * CSDL_Ext::createSurfaceWithBpp<4>(int, int);
+

+ 70 - 106
client/gui/SDL_Extensions.h

@@ -7,69 +7,25 @@
  * Full text of license available in license.txt file, in main folder
  *
  */
+
 #pragma once
-#include <SDL_version.h>
 #include <SDL_render.h>
-#include <SDL_video.h>
 #include <SDL_events.h>
-#include "../../lib/int3.h"
 #include "Geometries.h"
 #include "../../lib/GameConstants.h"
 
+struct SDL_Window;
+struct SDL_Renderer;
+struct SDL_Texture;
+struct SDL_Surface;
+struct SDL_Color;
 
 extern SDL_Window * mainWindow;
 extern SDL_Renderer * mainRenderer;
 extern SDL_Texture * screenTexture;
-
-inline void SDL_SetColors(SDL_Surface *surface, SDL_Color *colors, int firstcolor, int ncolors)
-{
-	SDL_SetPaletteColors(surface->format->palette,colors,firstcolor,ncolors);
-}
-
-inline void SDL_WarpMouse(int x, int y)
-{
-	SDL_WarpMouseInWindow(mainWindow,x,y);
-}
-
-void SDL_UpdateRect(SDL_Surface *surface, int x, int y, int w, int h);
-
-inline bool isCtrlKeyDown()
-{
-	return SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_LCTRL] || SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_RCTRL];
-}
-
-inline bool isAltKeyDown()
-{
-	return SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_LALT] || SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_RALT];
-}
-
-inline bool isShiftKeyDown()
-{
-	return SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_LSHIFT] || SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_RSHIFT];
-}
-namespace CSDL_Ext
-{
-	//todo: should this better be assignment operator?
-	STRONG_INLINE void colorAssign(SDL_Color & dest, const SDL_Color & source)
-	{
-		dest.r = source.r;
-		dest.g = source.g;
-		dest.b = source.b;
-		dest.a = source.a;
-	}
-
-	inline void setAlpha(SDL_Surface * bg, int value)
-	{
-		SDL_SetSurfaceAlphaMod(bg, value);
-	}
-}
-struct Rect;
-
 extern SDL_Surface * screen, *screen2, *screenBuf;
-void blitAt(SDL_Surface * src, int x, int y, SDL_Surface * dst=screen);
-void blitAt(SDL_Surface * src, const SDL_Rect & pos, SDL_Surface * dst=screen);
-bool isItIn(const SDL_Rect * rect, int x, int y);
-bool isItInOrLowerBounds(const SDL_Rect * rect, int x, int y);
+
+class Rect;
 
 /**
  * The colors class defines color constants of type SDL_Color.
@@ -97,14 +53,27 @@ public:
 
 	/** default key color for all 8 & 24 bit graphics */
 	static const SDL_Color DEFAULT_KEY_COLOR;
+
+	/// Selected creature card
+	static const SDL_Color RED;
+
+	/// Minimap border
+	static const SDL_Color PURPLE;
+
+	static const SDL_Color BLACK;
+
+	static const SDL_Color TRANSPARENT;
 };
 
-//MSVC gives an error when calling abs with ui64 -> we add template that will match calls with unsigned arg and return it
-template<typename T>
-typename boost::enable_if_c<boost::is_unsigned<T>::type, T>::type abs(T arg)
+namespace CSDL_Ext
 {
-	return arg;
-}
+
+void setColors(SDL_Surface *surface, SDL_Color *colors, int firstcolor, int ncolors);
+void warpMouse(int x, int y);
+bool isCtrlKeyDown();
+bool isAltKeyDown();
+bool isShiftKeyDown();
+void setAlpha(SDL_Surface * bg, int value);
 
 template<typename IntType>
 std::string makeNumberShort(IntType number, IntType maxLength = 3) //the output is a string containing at most 5 characters [4 if positive] (eg. intead 10000 it gives 10k)
@@ -126,12 +95,9 @@ std::string makeNumberShort(IntType number, IntType maxLength = 3) //the output
 	return boost::lexical_cast<std::string>(number) + *iter;
 }
 
-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);
-
-inline SDL_Rect genRect(const int & hh, const int & ww, const int & xx, const int & yy)
+inline Rect genRect(const int & hh, const int & ww, const int & xx, const int & yy)
 {
-	SDL_Rect ret;
+	Rect ret;
 	ret.h=hh;
 	ret.w=ww;
 	ret.x=xx;
@@ -139,52 +105,31 @@ inline SDL_Rect genRect(const int & hh, const int & ww, const int & xx, const in
 	return ret;
 }
 
-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);
-};
+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 (*BlitterWithRotationVal)(SDL_Surface *src,SDL_Rect srcRect, SDL_Surface * dst, SDL_Rect dstRect, ui8 rotation);
+	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);
 
-namespace CSDL_Ext
-{
-	/// helper that will safely set and un-set ClipRect for SDL_Surface
-	class CClipRectGuard
-	{
-		SDL_Surface * surf;
-		SDL_Rect oldRect;
-	public:
-		CClipRectGuard(SDL_Surface * surface, const SDL_Rect & rect):
-			surf(surface)
-		{
-			SDL_GetClipRect(surf, &oldRect);
-			SDL_SetClipRect(surf, &rect);
-		}
+	void setClipRect(SDL_Surface * src, const Rect & other);
+	void getClipRect(SDL_Surface * src, Rect & other);
 
-		~CClipRectGuard()
-		{
-			SDL_SetClipRect(surf, &oldRect);
-		}
-	};
+	void blitSurface(SDL_Surface * src, const Rect & srcRect, SDL_Surface * dst, const Point & dest);
+	void blitSurface(SDL_Surface * src, SDL_Surface * dst, const Point & dest);
 
-	void blitSurface(SDL_Surface * src, const SDL_Rect * srcRect, SDL_Surface * dst, SDL_Rect * dstRect);
-	void fillRect(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color);
-	void fillRectBlack(SDL_Surface * dst, SDL_Rect * dstrect);
+	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 SDL_PutPixelWithoutRefresh(SDL_Surface *ekran, const int & x, const int & y, const Uint8 & R, const Uint8 & G, const Uint8 & B, Uint8 A = 255);
-	void SDL_PutPixelWithoutRefreshIfInSurf(SDL_Surface *ekran, const int & x, const int & y, const Uint8 & R, const Uint8 & G, const Uint8 & B, Uint8 A = 255);
+	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);
 
 	SDL_Surface * verticalFlip(SDL_Surface * toRot); //vertical flip
 	SDL_Surface * horizontalFlip(SDL_Surface * toRot); //horizontal flip
-	Uint32 SDL_GetPixel(SDL_Surface *surface, const int & x, const int & y, bool colorByte = false);
+	Uint32 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
 
 	Uint8 *getPxPtr(const SDL_Surface * const &srf, const int x, const int y);
@@ -192,16 +137,16 @@ namespace CSDL_Ext
 	TColorPutterAlpha getPutterAlphaFor(SDL_Surface  * const &dest, int incrementing); //incrementing: -1, 0, 1
 
 	template<int bpp>
-	int blit8bppAlphaTo24bppT(const SDL_Surface * src, const SDL_Rect * srcRect, SDL_Surface * dst, SDL_Rect * dstRect); //blits 8 bpp surface with alpha channel to 24 bpp surface
-	int blit8bppAlphaTo24bpp(const SDL_Surface * src, const SDL_Rect * srcRect, SDL_Surface * dst, SDL_Rect * dstRect); //blits 8 bpp surface with alpha channel to 24 bpp surface
+	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
 	SDL_Color makeColor(ui8 r, ui8 g, ui8 b, ui8 a);
 
 	void update(SDL_Surface * what = screen); //updates whole surface (default - main screen)
 	void drawLine(SDL_Surface * sur, int x1, int y1, int x2, int y2, const SDL_Color & color1, const SDL_Color & color2);
-	void drawBorder(SDL_Surface * sur, int x, int y, int w, int h, const int3 &color);
-	void drawBorder(SDL_Surface * sur, const SDL_Rect &r, const int3 &color);
-	void drawDashedBorder(SDL_Surface * sur, const Rect &r, const int3 &color);
+	void drawBorder(SDL_Surface * sur, int x, int y, int w, int h, const SDL_Color &color);
+	void drawBorder(SDL_Surface * sur, const Rect &r, const SDL_Color &color);
+	void drawDashedBorder(SDL_Surface * sur, const Rect &r, const SDL_Color &color);
 	void setPlayerColor(SDL_Surface * sur, PlayerColor player); //sets correct color of flags; -1 for neutral
 	std::string processStr(std::string str, std::vector<std::string> & tor); //replaces %s in string
 	SDL_Surface * newSurface(int w, int h, SDL_Surface * mod=screen); //creates new surface, with flags/format same as in surface given
@@ -217,10 +162,10 @@ namespace CSDL_Ext
 	SDL_Surface * scaleSurface(SDL_Surface *surf, int width, int height);
 
 	template<int bpp>
-	void applyEffectBpp( SDL_Surface * surf, const SDL_Rect * rect, int mode );
-	void applyEffect(SDL_Surface * surf, const SDL_Rect * rect, int mode); //mode: 0 - sepia, 1 - grayscale
+	void applyEffectBpp( SDL_Surface * surf, const Rect & rect, int mode );
+	void applyEffect(SDL_Surface * surf, const Rect & rect, int mode); //mode: 0 - sepia, 1 - grayscale
 
-	void startTextInput(SDL_Rect * where);
+	void startTextInput(const Rect & where);
 	void stopTextInput();
 
 	void setColorKey(SDL_Surface * surface, SDL_Color color);
@@ -230,4 +175,23 @@ namespace CSDL_Ext
 
 	///set key-color to 0,255,255 only if it exactly mapped
 	void setDefaultColorKeyPresize(SDL_Surface * surface);
+
+	/// helper that will safely set and un-set ClipRect for SDL_Surface
+	class CClipRectGuard
+	{
+		SDL_Surface * surf;
+		Rect oldRect;
+	public:
+		CClipRectGuard(SDL_Surface * surface, const Rect & rect):
+			surf(surface)
+		{
+			CSDL_Ext::getClipRect(surf, oldRect);
+			CSDL_Ext::setClipRect(surf, rect);
+		}
+
+		~CClipRectGuard()
+		{
+			CSDL_Ext::setClipRect(surf, oldRect);
+		}
+	};
 }

+ 12 - 2
client/gui/SDL_Pixels.h

@@ -9,10 +9,10 @@
  */
 #pragma once
 
-#include <SDL_endian.h>
-
 #include "SDL_Extensions.h"
 
+#include <SDL_endian.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
 namespace Channels
@@ -119,6 +119,16 @@ 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);
+};
 
 template <int incrementPtr>
 struct ColorPutter<2, incrementPtr>

+ 3 - 2
client/mainmenu/CMainMenu.cpp

@@ -546,8 +546,9 @@ CLoadingScreen::~CLoadingScreen()
 
 void CLoadingScreen::showAll(SDL_Surface * to)
 {
-	Rect rect(0, 0, to->w, to->h);
-	SDL_FillRect(to, &rect, 0);
+	//FIXME: filling screen with transparency? BLACK intended?
+	//Rect rect(0, 0, to->w, to->h);
+	//CSDL_Ext::fillRect(to, rect, Colors::TRANSPARENCY);
 
 	CWindowObject::showAll(to);
 }

+ 1 - 1
client/mainmenu/CPrologEpilogVideo.cpp

@@ -39,7 +39,7 @@ CPrologEpilogVideo::CPrologEpilogVideo(CCampaignScenario::SScenarioPrologEpilog
 
 void CPrologEpilogVideo::show(SDL_Surface * to)
 {
-	CSDL_Ext::fillRectBlack(to, &pos);
+	CSDL_Ext::fillRect(to, pos, Colors::BLACK);
 	//BUG: some videos are 800x600 in size while some are 800x400
 	//VCMI should center them in the middle of the screen. Possible but needs modification
 	//of video player API which I'd like to avoid until we'll get rid of Windows-specific player

+ 42 - 42
client/mapHandler.cpp

@@ -288,7 +288,7 @@ void CMapHandler::initObjectRects()
 			for(int fy=0; fy < obj->getHeight(); ++fy)
 			{
 				int3 currTile(obj->pos.x - fx, obj->pos.y - fy, obj->pos.z);
-				SDL_Rect cr;
+				Rect cr;
 				cr.w = 32;
 				cr.h = 32;
 				cr.x = image->width() - fx * 32 - 32;
@@ -374,7 +374,7 @@ CMapHandler::CMapBlitter *CMapHandler::resolveBlitter(const MapDrawingInfo * inf
 	return normalBlitter;
 }
 
-void CMapHandler::CMapNormalBlitter::drawElement(EMapCacheType cacheType, std::shared_ptr<IImage> source, SDL_Rect * sourceRect, SDL_Surface * targetSurf, SDL_Rect * destRect) const
+void CMapHandler::CMapNormalBlitter::drawElement(EMapCacheType cacheType, std::shared_ptr<IImage> source, Rect * sourceRect, SDL_Surface * targetSurf, Rect * destRect) const
 {
 	source->draw(targetSurf, destRect, sourceRect);
 }
@@ -387,8 +387,8 @@ void CMapHandler::CMapNormalBlitter::init(const MapDrawingInfo * drawingInfo)
 	tileCount.y = parent->tilesH;
 
 	topTile = info->topTile;
-	initPos.x = parent->offsetX + info->drawBounds->x;
-	initPos.y = parent->offsetY + info->drawBounds->y;
+	initPos.x = parent->offsetX + info->drawBounds.x;
+	initPos.y = parent->offsetY + info->drawBounds.y;
 
 	realTileRect = Rect(initPos.x, initPos.y, tileSize, tileSize);
 
@@ -430,11 +430,11 @@ void CMapHandler::CMapNormalBlitter::init(const MapDrawingInfo * drawingInfo)
 		tileCount.y = parent->sizes.y + parent->frameH - topTile.y;
 }
 
-SDL_Rect CMapHandler::CMapNormalBlitter::clip(SDL_Surface * targetSurf) const
+Rect CMapHandler::CMapNormalBlitter::clip(SDL_Surface * targetSurf) const
 {
-	SDL_Rect prevClip;
-	SDL_GetClipRect(targetSurf, &prevClip);
-	SDL_SetClipRect(targetSurf, info->drawBounds);
+	Rect prevClip;
+	CSDL_Ext::getClipRect(targetSurf, prevClip);
+	CSDL_Ext::setClipRect(targetSurf, info->drawBounds);
 	return prevClip;
 }
 
@@ -512,7 +512,7 @@ void CMapHandler::CMapWorldViewBlitter::calculateWorldViewCameraPos()
 		topTile.y = parent->sizes.y - tileCount.y;
 }
 
-void CMapHandler::CMapWorldViewBlitter::drawElement(EMapCacheType cacheType, std::shared_ptr<IImage> source, SDL_Rect * sourceRect, SDL_Surface * targetSurf, SDL_Rect * destRect) const
+void CMapHandler::CMapWorldViewBlitter::drawElement(EMapCacheType cacheType, std::shared_ptr<IImage> source, Rect * sourceRect, SDL_Surface * targetSurf, Rect * destRect) const
 {
 	auto scaled = parent->cache.requestWorldViewCacheOrCreate(cacheType, source);
 
@@ -584,7 +584,7 @@ void CMapHandler::CMapWorldViewBlitter::drawOverlayEx(SDL_Surface * targetSurf)
 	}
 }
 
-void CMapHandler::CMapWorldViewBlitter::drawHeroFlag(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const
+void CMapHandler::CMapWorldViewBlitter::drawHeroFlag(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, Rect * sourceRect, Rect * destRect, bool moving) const
 {
 	if (moving)
 		return;
@@ -592,7 +592,7 @@ void CMapHandler::CMapWorldViewBlitter::drawHeroFlag(SDL_Surface * targetSurf, s
 	CMapBlitter::drawHeroFlag(targetSurf, source, sourceRect, destRect, false);
 }
 
-void CMapHandler::CMapWorldViewBlitter::drawObject(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, SDL_Rect * sourceRect, bool moving) const
+void CMapHandler::CMapWorldViewBlitter::drawObject(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, Rect * sourceRect, bool moving) const
 {
 	if (moving)
 		return;
@@ -625,11 +625,11 @@ void CMapHandler::CMapWorldViewBlitter::init(const MapDrawingInfo * drawingInfo)
 	tileSize = (int) floorf(32.0f * info->scale);
 	halfTileSizeCeil = (int)ceilf(tileSize / 2.0f);
 
-	tileCount.x = (int) ceilf((float)info->drawBounds->w / tileSize);
-	tileCount.y = (int) ceilf((float)info->drawBounds->h / tileSize);
+	tileCount.x = (int) ceilf((float)info->drawBounds.w / tileSize);
+	tileCount.y = (int) ceilf((float)info->drawBounds.h / tileSize);
 
-	initPos.x = info->drawBounds->x;
-	initPos.y = info->drawBounds->y;
+	initPos.x = info->drawBounds.x;
+	initPos.y = info->drawBounds.y;
 
 	realTileRect = Rect(initPos.x, initPos.y, tileSize, tileSize);
 	defaultTileRect = Rect(0, 0, tileSize, tileSize);
@@ -637,19 +637,19 @@ void CMapHandler::CMapWorldViewBlitter::init(const MapDrawingInfo * drawingInfo)
 	calculateWorldViewCameraPos();
 }
 
-SDL_Rect CMapHandler::CMapWorldViewBlitter::clip(SDL_Surface * targetSurf) const
+Rect CMapHandler::CMapWorldViewBlitter::clip(SDL_Surface * targetSurf) const
 {
-	SDL_Rect prevClip;
+	Rect prevClip;
 
-	SDL_FillRect(targetSurf, info->drawBounds, SDL_MapRGB(targetSurf->format, 0, 0, 0));
+	CSDL_Ext::fillRect(targetSurf, info->drawBounds, Colors::BLACK);
 	// makes the clip area smaller if the map is smaller than the screen frame
 	// (actually, it could be made 1 tile bigger so that overlay icons on edge tiles could be drawn partly outside)
-	Rect clipRect(std::max<int>(info->drawBounds->x, info->drawBounds->x - topTile.x * tileSize),
-				  std::max<int>(info->drawBounds->y, info->drawBounds->y - topTile.y * tileSize),
-				  std::min<int>(info->drawBounds->w, parent->sizes.x * tileSize),
-				  std::min<int>(info->drawBounds->h, parent->sizes.y * tileSize));
-	SDL_GetClipRect(targetSurf, &prevClip);
-	SDL_SetClipRect(targetSurf, &clipRect); //preventing blitting outside of that rect
+	Rect clipRect(std::max<int>(info->drawBounds.x, info->drawBounds.x - topTile.x * tileSize),
+				  std::max<int>(info->drawBounds.y, info->drawBounds.y - topTile.y * tileSize),
+				  std::min<int>(info->drawBounds.w, parent->sizes.x * tileSize),
+				  std::min<int>(info->drawBounds.h, parent->sizes.y * tileSize));
+	CSDL_Ext::getClipRect(targetSurf, prevClip);
+	CSDL_Ext::setClipRect(targetSurf, clipRect); //preventing blitting outside of that rect
 	return prevClip;
 }
 
@@ -715,12 +715,12 @@ void CMapHandler::CMapBlitter::drawOverlayEx(SDL_Surface * targetSurf)
 //nothing to do here
 }
 
-void CMapHandler::CMapBlitter::drawHeroFlag(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const
+void CMapHandler::CMapBlitter::drawHeroFlag(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, Rect * sourceRect, Rect * destRect, bool moving) const
 {
 	drawElement(EMapCacheType::HERO_FLAGS, source, sourceRect, targetSurf, destRect);
 }
 
-void CMapHandler::CMapBlitter::drawObject(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, SDL_Rect * sourceRect, bool moving) const
+void CMapHandler::CMapBlitter::drawObject(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, Rect * sourceRect, bool moving) const
 {
 	Rect dstRect(realTileRect);
 	drawElement(EMapCacheType::OBJECTS, source, sourceRect, targetSurf, &dstRect);
@@ -739,7 +739,7 @@ void CMapHandler::CMapBlitter::drawObjects(SDL_Surface * targetSurf, const Terra
 				// this object is currently fading, so skip normal drawing
 				Rect r2(realTileRect);
 				CFadeAnimation * fade = (*fadeIter).second.second;
-				fade->draw(targetSurf, nullptr, &r2);
+				fade->draw(targetSurf, r2.topLeft());
 				continue;
 			}
 			logGlobal->error("Fading map object with missing fade anim : %d", object.fadeAnimKey);
@@ -903,7 +903,7 @@ void CMapHandler::CMapBlitter::blit(SDL_Surface * targetSurf, const MapDrawingIn
 						if (!block)
 							block = BitmapHandler::loadBitmap("blocked");
 
-						CSDL_Ext::blitSurface(block, nullptr, targetSurf, &realTileRect);
+						CSDL_Ext::blitSurface(block, targetSurf, realTileRect.topLeft());
 					}
 				}
 				if (settings["session"]["showVisit"].Bool())
@@ -914,7 +914,7 @@ void CMapHandler::CMapBlitter::blit(SDL_Surface * targetSurf, const MapDrawingIn
 						if (!visit)
 							visit = BitmapHandler::loadBitmap("visitable");
 
-						CSDL_Ext::blitSurface(visit, nullptr, targetSurf, &realTileRect);
+						CSDL_Ext::blitSurface(visit, targetSurf, realTileRect.topLeft());
 					}
 				}
 			}
@@ -932,26 +932,26 @@ void CMapHandler::CMapBlitter::blit(SDL_Surface * targetSurf, const MapDrawingIn
 			{
 				const int3 color(0x555555, 0x555555, 0x555555);
 
-				if (realPos.y >= info->drawBounds->y &&
-					realPos.y < info->drawBounds->y + info->drawBounds->h)
+				if (realPos.y >= info->drawBounds.y &&
+					realPos.y < info->drawBounds.y + info->drawBounds.h)
 					for(int i = 0; i < tileSize; i++)
-						if (realPos.x + i >= info->drawBounds->x &&
-							realPos.x + i < info->drawBounds->x + info->drawBounds->w)
-							CSDL_Ext::SDL_PutPixelWithoutRefresh(targetSurf, realPos.x + i, realPos.y, color.x, color.y, color.z);
+						if (realPos.x + i >= info->drawBounds.x &&
+							realPos.x + i < info->drawBounds.x + info->drawBounds.w)
+							CSDL_Ext::putPixelWithoutRefresh(targetSurf, realPos.x + i, realPos.y, color.x, color.y, color.z);
 
-				if (realPos.x >= info->drawBounds->x &&
-					realPos.x < info->drawBounds->x + info->drawBounds->w)
+				if (realPos.x >= info->drawBounds.x &&
+					realPos.x < info->drawBounds.x + info->drawBounds.w)
 					for(int i = 0; i < tileSize; i++)
-						if (realPos.y + i >= info->drawBounds->y &&
-							realPos.y + i < info->drawBounds->y + info->drawBounds->h)
-							CSDL_Ext::SDL_PutPixelWithoutRefresh(targetSurf, realPos.x, realPos.y + i, color.x, color.y, color.z);
+						if (realPos.y + i >= info->drawBounds.y &&
+							realPos.y + i < info->drawBounds.y + info->drawBounds.h)
+							CSDL_Ext::putPixelWithoutRefresh(targetSurf, realPos.x, realPos.y + i, color.x, color.y, color.z);
 			}
 		}
 	}
 
 	postProcessing(targetSurf);
 
-	SDL_SetClipRect(targetSurf, &prevClip);
+	CSDL_Ext::setClipRect(targetSurf, prevClip);
 }
 
 CMapHandler::AnimBitmapHolder CMapHandler::CMapBlitter::findHeroBitmap(const CGHeroInstance * hero, int anim) const
@@ -1207,7 +1207,7 @@ bool CMapHandler::printObject(const CGObjectInstance * obj, bool fadein)
 	{
 		for(int fy=0; fy<tilesH; ++fy)
 		{
-			SDL_Rect cr;
+			Rect cr;
 			cr.w = 32;
 			cr.h = 32;
 			cr.x = fx*32;
@@ -1470,7 +1470,7 @@ bool CMapHandler::compareObjectBlitOrder(const CGObjectInstance * a, const CGObj
 	return false;
 }
 
-TerrainTileObject::TerrainTileObject(const CGObjectInstance * obj_, SDL_Rect rect_, bool visitablePos)
+TerrainTileObject::TerrainTileObject(const CGObjectInstance * obj_, Rect rect_, bool visitablePos)
 	: obj(obj_),
 	  rect(rect_),
 	  fadeAnimKey(-1)

+ 14 - 15
client/mapHandler.h

@@ -35,7 +35,6 @@ class PlayerColor;
 VCMI_LIB_NAMESPACE_END
 
 struct SDL_Surface;
-struct SDL_Rect;
 class CAnimation;
 class IImage;
 class CFadeAnimation;
@@ -80,11 +79,11 @@ enum class EMapAnimRedrawStatus
 struct TerrainTileObject
 {
 	const CGObjectInstance *obj;
-	SDL_Rect rect;
+	Rect rect;
 	int fadeAnimKey;
 	boost::optional<std::string> ambientSound;
 
-	TerrainTileObject(const CGObjectInstance *obj_, SDL_Rect rect_, bool visitablePos = false);
+	TerrainTileObject(const CGObjectInstance *obj_, Rect rect_, bool visitablePos = false);
 	~TerrainTileObject();
 };
 
@@ -98,7 +97,7 @@ struct MapDrawingInfo
 	bool scaled;
 	int3 &topTile; // top-left tile in viewport [in tiles]
 	std::shared_ptr<const boost::multi_array<ui8, 3>> visibilityMap;
-	SDL_Rect * drawBounds; // map rect drawing bounds on screen
+	Rect drawBounds; // map rect drawing bounds on screen
 	std::shared_ptr<CAnimation> icons; // holds overlay icons for world view mode
 	float scale; // map scale for world view mode (only if scaled == true)
 
@@ -115,7 +114,7 @@ struct MapDrawingInfo
 
 	bool showAllTerrain; //for expert viewEarth
 
-	MapDrawingInfo(int3 &topTile_, std::shared_ptr<const boost::multi_array<ui8, 3>> visibilityMap_, SDL_Rect * drawBounds_, std::shared_ptr<CAnimation> icons_ = nullptr)
+	MapDrawingInfo(int3 &topTile_, std::shared_ptr<const boost::multi_array<ui8, 3>> visibilityMap_, const Rect & drawBounds_, std::shared_ptr<CAnimation> icons_ = nullptr)
 		: scaled(false),
 		  topTile(topTile_),
 
@@ -216,7 +215,7 @@ class CMapHandler
 		const MapDrawingInfo * info; // data for drawing passed from outside
 
 		/// general drawing method, called internally by more specialized ones
-		virtual void drawElement(EMapCacheType cacheType, std::shared_ptr<IImage> source, SDL_Rect * sourceRect, SDL_Surface * targetSurf, SDL_Rect * destRect) const = 0;
+		virtual void drawElement(EMapCacheType cacheType, std::shared_ptr<IImage> source, Rect * sourceRect, SDL_Surface * targetSurf, Rect * destRect) const = 0;
 
 		// first drawing pass
 
@@ -228,8 +227,8 @@ class CMapHandler
 		virtual void drawRoad(SDL_Surface * targetSurf, const TerrainTile & tinfo, const TerrainTile * tinfoUpper) const;
 		/// draws all objects on current tile (higher-level logic, unlike other draw*** methods)
 		virtual void drawObjects(SDL_Surface * targetSurf, const TerrainTile2 & tile) const;
-		virtual void drawObject(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, SDL_Rect * sourceRect, bool moving) const;
-		virtual void drawHeroFlag(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const;
+		virtual void drawObject(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, Rect * sourceRect, bool moving) const;
+		virtual void drawHeroFlag(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, Rect * sourceRect, Rect * destRect, bool moving) const;
 
 		// second drawing pass
 
@@ -252,7 +251,7 @@ class CMapHandler
 		/// initializes frame-drawing (called at the start of every redraw)
 		virtual void init(const MapDrawingInfo * drawingInfo) = 0;
 		/// calculates clip region for map viewport
-		virtual SDL_Rect clip(SDL_Surface * targetSurf) const = 0;
+		virtual Rect clip(SDL_Surface * targetSurf) const = 0;
 
 		virtual ui8 getHeroFrameGroup(ui8 dir, bool isMoving) const;
 		virtual ui8 getPhaseShift(const CGObjectInstance *object) const;
@@ -279,10 +278,10 @@ class CMapHandler
 	class CMapNormalBlitter : public CMapBlitter
 	{
 	protected:
-		void drawElement(EMapCacheType cacheType, std::shared_ptr<IImage> source, SDL_Rect * sourceRect, SDL_Surface * targetSurf, SDL_Rect * destRect) const override;
+		void drawElement(EMapCacheType cacheType, std::shared_ptr<IImage> source, Rect * sourceRect, SDL_Surface * targetSurf, Rect * destRect) const override;
 		void drawTileOverlay(SDL_Surface * targetSurf,const TerrainTile2 & tile) const override {}
 		void init(const MapDrawingInfo * info) override;
-		SDL_Rect clip(SDL_Surface * targetSurf) const override;
+		Rect clip(SDL_Surface * targetSurf) const override;
 	public:
 		CMapNormalBlitter(CMapHandler * parent);
 		virtual ~CMapNormalBlitter(){}
@@ -293,14 +292,14 @@ class CMapHandler
 	private:
 		std::shared_ptr<IImage> objectToIcon(Obj id, si32 subId, PlayerColor owner) const;
 	protected:
-		void drawElement(EMapCacheType cacheType, std::shared_ptr<IImage> source, SDL_Rect * sourceRect, SDL_Surface * targetSurf, SDL_Rect * destRect) const override;
+		void drawElement(EMapCacheType cacheType, std::shared_ptr<IImage> source, Rect * sourceRect, SDL_Surface * targetSurf, Rect * destRect) const override;
 		void drawTileOverlay(SDL_Surface * targetSurf, const TerrainTile2 & tile) const override;
-		void drawHeroFlag(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const override;
-		void drawObject(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, SDL_Rect * sourceRect, bool moving) const override;
+		void drawHeroFlag(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, Rect * sourceRect, Rect * destRect, bool moving) const override;
+		void drawObject(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, Rect * sourceRect, bool moving) const override;
 		void drawFrame(SDL_Surface * targetSurf) const override {}
 		void drawOverlayEx(SDL_Surface * targetSurf) override;
 		void init(const MapDrawingInfo * info) override;
-		SDL_Rect clip(SDL_Surface * targetSurf) const override;
+		Rect clip(SDL_Surface * targetSurf) const override;
 		ui8 getPhaseShift(const CGObjectInstance *object) const override { return 0u; }
 		void calculateWorldViewCameraPos();
 	public:

+ 9 - 9
client/widgets/AdventureMapClasses.cpp

@@ -237,7 +237,7 @@ void CHeroList::CHeroItem::open()
 
 void CHeroList::CHeroItem::showTooltip()
 {
-	CRClickPopup::createAndPush(hero, Point(GH.current->motion));
+	CRClickPopup::createAndPush(hero, Geometry::fromSDL(GH.current->motion));
 }
 
 std::string CHeroList::CHeroItem::getHoverText()
@@ -329,7 +329,7 @@ void CTownList::CTownItem::open()
 
 void CTownList::CTownItem::showTooltip()
 {
-	CRClickPopup::createAndPush(town, Point(GH.current->motion));
+	CRClickPopup::createAndPush(town, Geometry::fromSDL(GH.current->motion));
 }
 
 std::string CTownList::CTownItem::getHoverText()
@@ -593,8 +593,8 @@ void CMinimap::showAll(SDL_Surface * to)
 		int3 tileCountOnScreen = adventureInt->terrain.tileCountOnScreen();
 
 		//draw radar
-		SDL_Rect oldClip;
-		SDL_Rect radar =
+		Rect oldClip;
+		Rect radar =
 		{
 			si16(adventureInt->position.x * pos.w / mapSizes.x + pos.x),
 			si16(adventureInt->position.y * pos.h / mapSizes.y + pos.y),
@@ -612,10 +612,10 @@ void CMinimap::showAll(SDL_Surface * to)
 				return; // whole map is visible at once, no point in redrawing border
 		}
 
-		SDL_GetClipRect(to, &oldClip);
-		SDL_SetClipRect(to, &pos);
-		CSDL_Ext::drawDashedBorder(to, radar, int3(255,75,125));
-		SDL_SetClipRect(to, &oldClip);
+		CSDL_Ext::getClipRect(to, oldClip);
+		CSDL_Ext::setClipRect(to, pos);
+		CSDL_Ext::drawDashedBorder(to, radar, Colors::PURPLE);
+		CSDL_Ext::setClipRect(to, oldClip);
 	}
 }
 
@@ -1224,7 +1224,7 @@ void CAdvMapPanel::setPlayerColor(const PlayerColor & clr)
 void CAdvMapPanel::showAll(SDL_Surface * to)
 {
 	if(background)
-		blitAt(background, pos.x, pos.y, to);
+		CSDL_Ext::blitAt(background, pos.x, pos.y, to);
 
 	CIntObject::showAll(to);
 }

+ 9 - 6
client/widgets/Buttons.cpp

@@ -28,10 +28,12 @@ void CButton::update()
 {
 	if (overlay)
 	{
+		Point targetPos = Rect::createCentered( pos, overlay->pos.dimensions()).topLeft();
+
 		if (state == PRESSED)
-			overlay->moveTo(overlay->pos.centerIn(pos).topLeft() + Point(1,1));
+			overlay->moveTo(targetPos + Point(1,1));
 		else
-			overlay->moveTo(overlay->pos.centerIn(pos).topLeft());
+			overlay->moveTo(targetPos);
 	}
 
 	int newPos = stateToIndex[int(state)];
@@ -88,7 +90,8 @@ void CButton::addOverlay(std::shared_ptr<CIntObject> newOverlay)
 	if(overlay)
 	{
 		addChild(newOverlay.get());
-		overlay->moveTo(overlay->pos.centerIn(pos).topLeft());
+		Point targetPos = Rect::createCentered( pos, overlay->pos.dimensions()).topLeft();
+		overlay->moveTo(targetPos);
 	}
 	update();
 }
@@ -277,8 +280,8 @@ void CButton::showAll(SDL_Surface * to)
 	CIntObject::showAll(to);
 
 	auto borderColor = stateToBorderColor[getState()];
-	if (borderColor && borderColor->a == 0)
-		CSDL_Ext::drawBorder(to, pos.x-1, pos.y-1, pos.w+2, pos.h+2, int3(borderColor->r, borderColor->g, borderColor->b));
+	if (borderColor)
+		CSDL_Ext::drawBorder(to, pos.x-1, pos.y-1, pos.w+2, pos.h+2, *borderColor);
 }
 
 std::pair<std::string, std::string> CButton::tooltip()
@@ -765,7 +768,7 @@ void CSlider::setAmount( int to )
 
 void CSlider::showAll(SDL_Surface * to)
 {
-	CSDL_Ext::fillRectBlack(to, &pos);
+	CSDL_Ext::fillRect(to, pos, Colors::BLACK);
 	CIntObject::showAll(to);
 }
 

+ 1 - 2
client/widgets/Buttons.h

@@ -11,7 +11,6 @@
 
 #include "../gui/CIntObject.h"
 #include "../gui/SDL_Extensions.h"
-
 #include "../../lib/FunctionList.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
@@ -24,7 +23,7 @@ struct ButtonInfo;
 VCMI_LIB_NAMESPACE_END
 
 struct SDL_Surface;
-struct Rect;
+class Rect;
 class CAnimImage;
 class CLabel;
 class CAnimation;

+ 4 - 4
client/widgets/CArtifactHolder.cpp

@@ -340,15 +340,15 @@ void CHeroArtPlace::showAll(SDL_Surface * to)
 		// Draw vertical bars.
 		for (int i = 0; i < pos.h; ++i)
 		{
-			CSDL_Ext::SDL_PutPixelWithoutRefresh(to, pos.x,             pos.y + i, 240, 220, 120);
-			CSDL_Ext::SDL_PutPixelWithoutRefresh(to, pos.x + pos.w - 1, pos.y + i, 240, 220, 120);
+			CSDL_Ext::putPixelWithoutRefresh(to, pos.x,             pos.y + i, 240, 220, 120);
+			CSDL_Ext::putPixelWithoutRefresh(to, pos.x + pos.w - 1, pos.y + i, 240, 220, 120);
 		}
 
 		// Draw horizontal bars.
 		for (int i = 0; i < pos.w; ++i)
 		{
-			CSDL_Ext::SDL_PutPixelWithoutRefresh(to, pos.x + i, pos.y,             240, 220, 120);
-			CSDL_Ext::SDL_PutPixelWithoutRefresh(to, pos.x + i, pos.y + pos.h - 1, 240, 220, 120);
+			CSDL_Ext::putPixelWithoutRefresh(to, pos.x + i, pos.y,             240, 220, 120);
+			CSDL_Ext::putPixelWithoutRefresh(to, pos.x + i, pos.y + pos.h - 1, 240, 220, 120);
 		}
 	}
 }

+ 1 - 1
client/widgets/CComponent.cpp

@@ -296,7 +296,7 @@ void CSelectableComponent::showAll(SDL_Surface * to)
 	CComponent::showAll(to);
 	if(selected)
 	{
-		CSDL_Ext::drawBorder(to, Rect::around(image->pos), int3(239,215,123));
+		CSDL_Ext::drawBorder(to, Rect::createAround(image->pos, 1), Colors::BRIGHT_YELLOW);
 	}
 }
 

+ 2 - 9
client/widgets/Images.cpp

@@ -129,16 +129,9 @@ void CPicture::showAll(SDL_Surface * to)
 	if(bg && visible)
 	{
 		if(srcRect)
-		{
-			SDL_Rect srcRectCpy = *srcRect;
-			SDL_Rect dstRect = srcRectCpy;
-			dstRect.x = pos.x;
-			dstRect.y = pos.y;
-
-			CSDL_Ext::blitSurface(bg, &srcRectCpy, to, &dstRect);
-		}
+			CSDL_Ext::blitSurface(bg, *srcRect, to, pos.topLeft());
 		else
-			blitAt(bg, pos, to);
+			CSDL_Ext::blitAt(bg, pos, to);
 	}
 }
 

+ 3 - 2
client/widgets/Images.h

@@ -10,11 +10,12 @@
 #pragma once
 
 #include "../gui/CIntObject.h"
-#include "../gui/SDL_Extensions.h"
 #include "../battle/BattleConstants.h"
 
+#include <SDL_render.h>
+
 struct SDL_Surface;
-struct Rect;
+class Rect;
 class CAnimImage;
 class CLabel;
 class CAnimation;

+ 1 - 1
client/widgets/ObjectLists.h

@@ -12,7 +12,7 @@
 #include "../gui/CIntObject.h"
 
 struct SDL_Surface;
-struct Rect;
+class Rect;
 class CAnimImage;
 class CSlider;
 class CLabel;

+ 3 - 3
client/widgets/TextControls.cpp

@@ -349,7 +349,7 @@ void CGStatusBar::setEnteringMode(bool on)
 	{
 		assert(enteringText == false);
 		alignment = ETextAlignment::TOPLEFT;
-		CSDL_Ext::startTextInput(&pos);
+		CSDL_Ext::startTextInput(pos);
 		setText(consoleText);
 	}
 	else
@@ -505,7 +505,7 @@ CTextInput::CTextInput(const Rect & Pos, SDL_Surface * srf)
 	background = std::make_shared<CPicture>(Pos, 0, true);
 	Rect hlp = Pos;
 	if(srf)
-		CSDL_Ext::blitSurface(srf, &hlp, background->getSurface(), nullptr);
+		CSDL_Ext::blitSurface(srf, hlp, background->getSurface(), Point(0,0));
 	else
 		SDL_FillRect(background->getSurface(), nullptr, 0);
 	pos.w = background->pos.w;
@@ -527,7 +527,7 @@ CKeyboardFocusListener::CKeyboardFocusListener(CTextInput * textInput)
 
 void CKeyboardFocusListener::focusGot()
 {
-	CSDL_Ext::startTextInput(&textInput->pos);
+	CSDL_Ext::startTextInput(textInput->pos);
 	usageIndex++;
 }
 

+ 11 - 11
client/windows/CAdvmapInterface.cpp

@@ -248,7 +248,7 @@ void CTerrainRect::hover(bool on)
 	}
 	//Hoverable::hover(on);
 }
-void CTerrainRect::showPath(const SDL_Rect * extRect, SDL_Surface * to)
+void CTerrainRect::showPath(const Rect & extRect, SDL_Surface * to)
 {
 	const static int pns[9][9] = {
 				{16, 17, 18,  7, -1, 19,  6,  5, -1},
@@ -319,9 +319,9 @@ void CTerrainRect::showPath(const SDL_Rect * extRect, SDL_Surface * to)
 			int hvx = (x + arrow->width())  - (pos.x + pos.w),
 				hvy = (y + arrow->height()) - (pos.y + pos.h);
 
-			SDL_Rect prevClip;
-			SDL_GetClipRect(to, &prevClip);
-			SDL_SetClipRect(to, extRect); //preventing blitting outside of that rect
+			Rect prevClip;
+			CSDL_Ext::getClipRect(to, prevClip);
+			CSDL_Ext::setClipRect(to, extRect); //preventing blitting outside of that rect
 
 			if(ADVOPT.smoothMove) //version for smooth hero move, with pos shifts
 			{
@@ -367,7 +367,7 @@ void CTerrainRect::showPath(const SDL_Rect * extRect, SDL_Surface * to)
 					arrow->draw(to, x, y, &srcRect);
 				}
 			}
-			SDL_SetClipRect(to, &prevClip);
+			CSDL_Ext::setClipRect(to, prevClip);
 
 		}
 	} //for (int i=0;i<currentPath->nodes.size()-1;i++)
@@ -377,7 +377,7 @@ void CTerrainRect::show(SDL_Surface * to)
 {
 	if (adventureInt->mode == EAdvMapMode::NORMAL)
 	{
-		MapDrawingInfo info(adventureInt->position, LOCPLINT->cb->getVisibilityMap(), &pos);
+		MapDrawingInfo info(adventureInt->position, LOCPLINT->cb->getVisibilityMap(), pos);
 		info.otherheroAnim = true;
 		info.anim = adventureInt->anim;
 		info.heroAnim = adventureInt->heroAnim;
@@ -389,12 +389,12 @@ void CTerrainRect::show(SDL_Surface * to)
 		{
 			Rect r(pos);
 			fadeAnim->update();
-			fadeAnim->draw(to, nullptr, &r);
+			fadeAnim->draw(to, r.topLeft());
 		}
 
 		if (currentPath/* && adventureInt->position.z==currentPath->startPos().z*/) //drawing path
 		{
-			showPath(&pos, to);
+			showPath(pos, to);
 		}
 	}
 }
@@ -404,7 +404,7 @@ void CTerrainRect::showAll(SDL_Surface * to)
 	// world view map is static and doesn't need redraw every frame
 	if (adventureInt->mode == EAdvMapMode::WORLD_VIEW)
 	{
-		MapDrawingInfo info(adventureInt->position, LOCPLINT->cb->getVisibilityMap(), &pos, adventureInt->worldViewIcons);
+		MapDrawingInfo info(adventureInt->position, LOCPLINT->cb->getVisibilityMap(), pos, adventureInt->worldViewIcons);
 		info.scaled = true;
 		info.scale = adventureInt->worldViewScale;
 		adventureInt->worldViewOptions.adjustDrawingInfo(info);
@@ -460,7 +460,7 @@ void CTerrainRect::fadeFromCurrentView()
 
 	if (!fadeSurface)
 		fadeSurface = CSDL_Ext::newSurface(pos.w, pos.h);
-	SDL_BlitSurface(screen, &pos, fadeSurface, nullptr);
+	CSDL_Ext::blitSurface(screen, fadeSurface, Point(0,0));
 	fadeAnim->init(CFadeAnimation::EMode::OUT, fadeSurface);
 }
 
@@ -1814,7 +1814,7 @@ void CAdvMapInt::tileRClicked(const int3 &mapPos)
 		return;
 	}
 
-	CRClickPopup::createAndPush(obj, Point(GH.current->motion), ETextAlignment::CENTER);
+	CRClickPopup::createAndPush(obj, Geometry::fromSDL(GH.current->motion), ETextAlignment::CENTER);
 }
 
 void CAdvMapInt::enterCastingMode(const CSpell * sp)

+ 1 - 1
client/windows/CAdvmapInterface.h

@@ -91,7 +91,7 @@ public:
 	void show(SDL_Surface * to) override;
 	void showAll(SDL_Surface * to) override;
 	void showAnim(SDL_Surface * to);
-	void showPath(const SDL_Rect * extRect, SDL_Surface * to);
+	void showPath(const Rect &extRect, SDL_Surface * to);
 	int3 whichTileIsIt(const int x, const int y); //x,y are cursor position
 	int3 whichTileIsIt(); //uses current cursor pos
 	/// @returns number of visible tiles on screen respecting current map scaling

+ 3 - 3
client/windows/CCastleInterface.cpp

@@ -208,9 +208,9 @@ void CBuildingRect::show(SDL_Surface * to)
 			else
 				newColor = oldColor;
 
-			SDL_SetColors(border, &newColor, colorID, 1);
+			CSDL_Ext::setColors(border, &newColor, colorID, 1);
 			blitAtLoc(border, 0, 0, to);
-			SDL_SetColors(border, &oldColor, colorID, 1);
+			CSDL_Ext::setColors(border, &oldColor, colorID, 1);
 		}
 	}
 	if(stateTimeCounter < BUILD_ANIMATION_FINISHED_TIMEPOINT)
@@ -254,7 +254,7 @@ std::string CBuildingRect::getSubtitle()//hover text for building
 
 void CBuildingRect::mouseMoved (const SDL_MouseMotionEvent & sEvent)
 {
-	if(area && isItIn(&pos,sEvent.x, sEvent.y))
+	if(area && pos.isInside(sEvent.x, sEvent.y))
 	{
 		if(CSDL_Ext::isTransparent(area, GH.current->motion.x-pos.x, GH.current->motion.y-pos.y)) //hovered pixel is inside this building
 		{

+ 2 - 2
client/windows/CKingdomInterface.cpp

@@ -72,9 +72,9 @@ InfoBox::InfoBox(Point position, InfoPos Pos, InfoSize Size, std::shared_ptr<IIn
 	}
 
 	if(name)
-		pos = pos | name->pos;
+		pos = pos.include(name->pos);
 	if(value)
-		pos = pos | value->pos;
+		pos = pos.include(value->pos);
 
 	hover = std::make_shared<CHoverableArea>();
 	hover->hoverText = data->getHoverText();

+ 2 - 2
client/windows/CQuestLog.cpp

@@ -208,10 +208,10 @@ void CQuestLog::showAll(SDL_Surface * to)
 	if(questIndex >= 0 && questIndex < labels.size())
 	{
 		//TODO: use child object to selection rect
-		Rect rect = Rect::around(labels[questIndex]->pos);
+		Rect rect = Rect::createAround(labels[questIndex]->pos, 1);
 		rect.x -= 2; // Adjustment needed as we want selection box on top of border in graphics
 		rect.w += 2;
-		CSDL_Ext::drawBorder(to, rect, int3(Colors::METALLIC_GOLD.r, Colors::METALLIC_GOLD.g, Colors::METALLIC_GOLD.b));
+		CSDL_Ext::drawBorder(to, rect, Colors::METALLIC_GOLD);
 	}
 }
 

+ 14 - 14
client/windows/CSpellWindow.cpp

@@ -42,7 +42,7 @@
 
 #include "../../lib/mapObjects/CGHeroInstance.h"
 
-CSpellWindow::InteractiveArea::InteractiveArea(const SDL_Rect & myRect, std::function<void()> funcL, int helpTextId, CSpellWindow * _owner)
+CSpellWindow::InteractiveArea::InteractiveArea(const Rect & myRect, std::function<void()> funcL, int helpTextId, CSpellWindow * _owner)
 {
 	addUsedEvents(LCLICK | RCLICK | HOVER);
 	pos = myRect;
@@ -186,29 +186,29 @@ CSpellWindow::CSpellWindow(const CGHeroInstance * _myHero, CPlayerInterface * _m
 	mana = std::make_shared<CLabel>(435, 426, FONT_SMALL, ETextAlignment::CENTER, Colors::YELLOW, boost::lexical_cast<std::string>(myHero->mana));
 	statusBar = CGStatusBar::create(7, 569, "Spelroll.bmp");
 
-	SDL_Rect temp_rect = genRect(45, 35, 479 + pos.x, 405 + pos.y);
+	Rect temp_rect = CSDL_Ext::genRect(45, 35, 479 + pos.x, 405 + pos.y);
 	interactiveAreas.push_back(std::make_shared<InteractiveArea>(temp_rect, std::bind(&CSpellWindow::fexitb, this), 460, this));
-	temp_rect = genRect(45, 35, 221 + pos.x, 405 + pos.y);
+	temp_rect = CSDL_Ext::genRect(45, 35, 221 + pos.x, 405 + pos.y);
 	interactiveAreas.push_back(std::make_shared<InteractiveArea>(temp_rect, std::bind(&CSpellWindow::fbattleSpellsb, this), 453, this));
-	temp_rect = genRect(45, 35, 355 + pos.x, 405 + pos.y);
+	temp_rect = CSDL_Ext::genRect(45, 35, 355 + pos.x, 405 + pos.y);
 	interactiveAreas.push_back(std::make_shared<InteractiveArea>(temp_rect, std::bind(&CSpellWindow::fadvSpellsb, this), 452, this));
-	temp_rect = genRect(45, 35, 418 + pos.x, 405 + pos.y);
+	temp_rect = CSDL_Ext::genRect(45, 35, 418 + pos.x, 405 + pos.y);
 	interactiveAreas.push_back(std::make_shared<InteractiveArea>(temp_rect, std::bind(&CSpellWindow::fmanaPtsb, this), 459, this));
 
-	temp_rect = genRect(36, 56, 549 + pos.x, 94 + pos.y);
+	temp_rect = CSDL_Ext::genRect(36, 56, 549 + pos.x, 94 + pos.y);
 	interactiveAreas.push_back(std::make_shared<InteractiveArea>(temp_rect, std::bind(&CSpellWindow::selectSchool, this, 0), 454, this));
-	temp_rect = genRect(36, 56, 549 + pos.x, 151 + pos.y);
+	temp_rect = CSDL_Ext::genRect(36, 56, 549 + pos.x, 151 + pos.y);
 	interactiveAreas.push_back(std::make_shared<InteractiveArea>(temp_rect, std::bind(&CSpellWindow::selectSchool, this, 3), 457, this));
-	temp_rect = genRect(36, 56, 549 + pos.x, 210 + pos.y);
+	temp_rect = CSDL_Ext::genRect(36, 56, 549 + pos.x, 210 + pos.y);
 	interactiveAreas.push_back(std::make_shared<InteractiveArea>(temp_rect, std::bind(&CSpellWindow::selectSchool, this, 1), 455, this));
-	temp_rect = genRect(36, 56, 549 + pos.x, 270 + pos.y);
+	temp_rect = CSDL_Ext::genRect(36, 56, 549 + pos.x, 270 + pos.y);
 	interactiveAreas.push_back(std::make_shared<InteractiveArea>(temp_rect, std::bind(&CSpellWindow::selectSchool, this, 2), 456, this));
-	temp_rect = genRect(36, 56, 549 + pos.x, 330 + pos.y);
+	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 = genRect(leftCorner->bg->h, leftCorner->bg->w, 97 + pos.x, 77 + pos.y);
+	temp_rect = CSDL_Ext::genRect(leftCorner->bg->h, leftCorner->bg->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 = genRect(rightCorner->bg->h, rightCorner->bg->w, 487 + pos.x, 72 + pos.y);
+	temp_rect = CSDL_Ext::genRect(rightCorner->bg->h, rightCorner->bg->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
@@ -216,7 +216,7 @@ CSpellWindow::CSpellWindow(const CGHeroInstance * _myHero, CPlayerInterface * _m
 
 	for(int v=0; v<12; ++v)
 	{
-		temp_rect = genRect(65, 78, xpos, ypos);
+		temp_rect = CSDL_Ext::genRect(65, 78, xpos, ypos);
 		spellAreas[v] = std::make_shared<SpellArea>(temp_rect, this);
 
 		if(v == 5) //to right page
@@ -494,7 +494,7 @@ int CSpellWindow::pagesWithinCurrentTab()
 	return battleSpellsOnly ? sitesPerTabBattle[selectedTab] : sitesPerTabAdv[selectedTab];
 }
 
-CSpellWindow::SpellArea::SpellArea(SDL_Rect pos, CSpellWindow * owner)
+CSpellWindow::SpellArea::SpellArea(Rect pos, CSpellWindow * owner)
 {
 	this->pos = pos;
 	this->owner = owner;

+ 2 - 3
client/windows/CSpellWindow.h

@@ -19,7 +19,6 @@ class CSpell;
 VCMI_LIB_NAMESPACE_END
 
 struct SDL_Surface;
-struct SDL_Rect;
 class IImage;
 class CAnimImage;
 class CPicture;
@@ -42,7 +41,7 @@ class CSpellWindow : public CWindowObject
 		std::shared_ptr<CLabel> level;
 		std::shared_ptr<CLabel> cost;
 	public:
-		SpellArea(SDL_Rect pos, CSpellWindow * owner);
+		SpellArea(Rect pos, CSpellWindow * owner);
 		~SpellArea();
 		void setSpell(const CSpell * spell);
 
@@ -63,7 +62,7 @@ class CSpellWindow : public CWindowObject
 		void clickRight(tribool down, bool previousState) override;
 		void hover(bool on) override;
 
-		InteractiveArea(const SDL_Rect & myRect, std::function<void()> funcL, int helpTextId, CSpellWindow * _owner);
+		InteractiveArea(const Rect &myRect, std::function<void()> funcL, int helpTextId, CSpellWindow * _owner);
 	};
 
 	std::shared_ptr<CAnimation> spellIcons;

+ 5 - 5
client/windows/CTradeWindow.cpp

@@ -501,9 +501,9 @@ void CTradeWindow::getPositionsFor(std::vector<Rect> &poss, bool Left, EType typ
 
 		const std::vector<Rect> tmp =
 		{
-			genRect(h, w, x, y), genRect(h, w, x + dx, y), genRect(h, w, x + 2*dx, y),
-			genRect(h, w, x, y + dy), genRect(h, w, x + dx, y + dy), genRect(h, w, x + 2*dx, y + dy),
-			genRect(h, w, x + dx, y + 2*dy)
+			CSDL_Ext::genRect(h, w, x, y), CSDL_Ext::genRect(h, w, x + dx, y), CSDL_Ext::genRect(h, w, x + 2*dx, y),
+			CSDL_Ext::genRect(h, w, x, y + dy), CSDL_Ext::genRect(h, w, x + dx, y + dy), CSDL_Ext::genRect(h, w, x + 2*dx, y + dy),
+			CSDL_Ext::genRect(h, w, x + dx, y + 2*dy)
 		};
 
 		vstd::concatenate(poss, tmp);
@@ -564,9 +564,9 @@ void CTradeWindow::showAll(SDL_Surface * to)
 	CWindowObject::showAll(to);
 
 	if(hRight)
-		CSDL_Ext::drawBorder(to, hRight->pos.x-1, hRight->pos.y-1, hRight->pos.w+2, hRight->pos.h+2, int3(255,231,148));
+		CSDL_Ext::drawBorder(to, hRight->pos.x-1, hRight->pos.y-1, hRight->pos.w+2, hRight->pos.h+2, Colors::BRIGHT_YELLOW);
 	if(hLeft && hLeft->type != ARTIFACT_INSTANCE)
-		CSDL_Ext::drawBorder(to, hLeft->pos.x-1, hLeft->pos.y-1, hLeft->pos.w+2, hLeft->pos.h+2, int3(255,231,148));
+		CSDL_Ext::drawBorder(to, hLeft->pos.x-1, hLeft->pos.y-1, hLeft->pos.w+2, hLeft->pos.h+2, Colors::BRIGHT_YELLOW);
 
 	if(readyToTrade)
 	{

+ 3 - 5
client/windows/CWindowObject.cpp

@@ -170,12 +170,10 @@ void CWindowObject::setShadow(bool on)
 			shadowBottomTempl = CSDL_Ext::createSurfaceWithBpp<4>(1, size);
 			shadowRightTempl  = CSDL_Ext::createSurfaceWithBpp<4>(size, 1);
 
-			Uint32 shadowColor = SDL_MapRGBA(shadowCornerTempl->format, 0, 0, 0, 192);
-
 			//fill with shadow body color
-			SDL_FillRect(shadowCornerTempl, nullptr, shadowColor);
-			SDL_FillRect(shadowBottomTempl, nullptr, shadowColor);
-			SDL_FillRect(shadowRightTempl,  nullptr, shadowColor);
+			CSDL_Ext::fillSurface(shadowCornerTempl, { 0, 0, 0, 192 } );
+			CSDL_Ext::fillSurface(shadowBottomTempl, { 0, 0, 0, 192 } );
+			CSDL_Ext::fillSurface(shadowRightTempl,  { 0, 0, 0, 192 } );
 
 			//fill last row and column with more transparent color
 			blitAlphaCol(shadowRightTempl , size-1);

+ 11 - 11
client/windows/GUIClasses.cpp

@@ -102,9 +102,9 @@ void CRecruitmentWindow::CCreatureCard::showAll(SDL_Surface * to)
 {
 	CIntObject::showAll(to);
 	if(selected)
-		drawBorder(to, pos, int3(248, 0, 0));
+		drawBorder(to, pos, Colors::RED);
 	else
-		drawBorder(to, pos, int3(232, 212, 120));
+		drawBorder(to, pos, Colors::YELLOW);
 }
 
 void CRecruitmentWindow::select(std::shared_ptr<CCreatureCard> card)
@@ -179,17 +179,17 @@ void CRecruitmentWindow::showAll(SDL_Surface * to)
 	CWindowObject::showAll(to);
 
 	// recruit\total values
-	drawBorder(to, pos.x + 172, pos.y + 222, 67, 42, int3(239,215,123));
-	drawBorder(to, pos.x + 246, pos.y + 222, 67, 42, int3(239,215,123));
+	drawBorder(to, pos.x + 172, pos.y + 222, 67, 42, Colors::YELLOW);
+	drawBorder(to, pos.x + 246, pos.y + 222, 67, 42, Colors::YELLOW);
 
 	//cost boxes
-	drawBorder(to, pos.x + 64,  pos.y + 222, 99, 76, int3(239,215,123));
-	drawBorder(to, pos.x + 322, pos.y + 222, 99, 76, int3(239,215,123));
+	drawBorder(to, pos.x + 64,  pos.y + 222, 99, 76, Colors::YELLOW);
+	drawBorder(to, pos.x + 322, pos.y + 222, 99, 76, Colors::YELLOW);
 
 	//buttons borders
-	drawBorder(to, pos.x + 133, pos.y + 312, 66, 34, int3(173,142,66));
-	drawBorder(to, pos.x + 211, pos.y + 312, 66, 34, int3(173,142,66));
-	drawBorder(to, pos.x + 289, pos.y + 312, 66, 34, int3(173,142,66));
+	drawBorder(to, pos.x + 133, pos.y + 312, 66, 34, Colors::METALLIC_GOLD);
+	drawBorder(to, pos.x + 211, pos.y + 312, 66, 34, Colors::METALLIC_GOLD);
+	drawBorder(to, pos.x + 289, pos.y + 312, 66, 34, Colors::METALLIC_GOLD);
 }
 
 CRecruitmentWindow::CRecruitmentWindow(const CGDwelling * Dwelling, int Level, const CArmedInstance * Dst, const std::function<void(CreatureID,int)> & Recruit, int y_offset):
@@ -747,7 +747,7 @@ void CTavernWindow::show(SDL_Surface * to)
 		}
 
 		printAtMiddleWBLoc(sel->description, 146, 395, FONT_SMALL, 200, Colors::WHITE, to);
-		CSDL_Ext::drawBorder(to,sel->pos.x-2,sel->pos.y-2,sel->pos.w+4,sel->pos.h+4,int3(247,223,123));
+		CSDL_Ext::drawBorder(to,sel->pos.x-2,sel->pos.y-2,sel->pos.w+4,sel->pos.h+4,Colors::BRIGHT_YELLOW);
 	}
 }
 
@@ -1383,7 +1383,7 @@ void CPuzzleWindow::showAll(SDL_Surface * to)
 	Rect mapRect = genRect(544, 591, pos.x + 8, pos.y + 7);
 	int3 topTile = grailPos - moveInt;
 
-	MapDrawingInfo info(topTile, LOCPLINT->cb->getVisibilityMap(), &mapRect);
+	MapDrawingInfo info(topTile, LOCPLINT->cb->getVisibilityMap(), mapRect);
 	info.puzzleMode = true;
 	info.grailPos = grailPos;
 	CGI->mh->drawTerrainRectNew(to, &info);

+ 1 - 0
client/windows/GUIClasses.h

@@ -13,6 +13,7 @@
 #include "../lib/GameConstants.h"
 #include "../lib/ResourceSet.h"
 #include "../lib/CConfigHandler.h"
+#include "../lib/int3.h"
 #include "../widgets/CArtifactHolder.h"
 #include "../widgets/CGarrisonInt.h"
 #include "../widgets/Images.h"

+ 3 - 3
client/windows/InfoWindows.cpp

@@ -42,7 +42,7 @@
 void CSimpleWindow::show(SDL_Surface * to)
 {
 	if(bitmap)
-		blitAt(bitmap,pos.x,pos.y,to);
+		CSDL_Ext::blitAt(bitmap,pos.x,pos.y,to);
 }
 CSimpleWindow::~CSimpleWindow()
 {
@@ -262,7 +262,7 @@ void CInfoPopup::close()
 
 void CInfoPopup::show(SDL_Surface * to)
 {
-	blitAt(bitmap,pos.x,pos.y,to);
+	CSDL_Ext::blitAt(bitmap,pos.x,pos.y,to);
 }
 
 CInfoPopup::~CInfoPopup()
@@ -306,7 +306,7 @@ void CRClickPopup::createAndPush(const std::string &txt, const CInfoWindow::TCom
 		player = PlayerColor(1);
 
 	auto temp = std::make_shared<CInfoWindow>(txt, player, comps);
-	temp->center(Point(GH.current->motion)); //center on mouse
+	temp->center(Geometry::fromSDL(GH.current->motion)); //center on mouse
 #ifdef VCMI_IOS
     // TODO: enable also for android?
     temp->moveBy({0, -temp->pos.h / 2});

+ 1 - 1
client/windows/InfoWindows.h

@@ -19,7 +19,7 @@ class CGGarrison;
 VCMI_LIB_NAMESPACE_END
 
 struct SDL_Surface;
-struct Rect;
+class Rect;
 class CAnimImage;
 class CLabel;
 class CAnimation;

+ 3 - 3
lib/Rect.h

@@ -46,15 +46,15 @@ public:
 	DLL_LINKAGE static Rect createCentered( const Rect  & target, const Point & size );
 	DLL_LINKAGE static Rect createAround(const Rect &r, int borderWidth);
 
-	bool isIn(int qx, int qy) const
+	bool isInside(int qx, int qy) const
 	{
 		if (qx > x && qx<x+w && qy>y && qy<y+h)
 			return true;
 		return false;
 	}
-	bool isIn(const Point & q) const
+	bool isInside(const Point & q) const
 	{
-		return isIn(q.x,q.y);
+		return isInside(q.x,q.y);
 	}
 	int top() const
 	{