瀏覽代碼

CPicture now uses IImage internally

Ivan Savenko 2 年之前
父節點
當前提交
87218c63c4

+ 1 - 1
client/CMessage.cpp

@@ -97,7 +97,7 @@ void CMessage::dispose()
 SDL_Surface * CMessage::drawDialogBox(int w, int h, PlayerColor playerColor)
 {
 	//prepare surface
-	SDL_Surface * ret = SDL_CreateRGBSurface(0, w, h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
+	SDL_Surface * ret = CSDL_Ext::newSurface(w,h);
 	for (int i=0; i<w; i+=background->w)//background
 	{
 		for (int j=0; j<h; j+=background->h)

+ 28 - 8
client/gui/CAnimation.cpp

@@ -97,7 +97,7 @@ public:
 
 	void draw(SDL_Surface * where, int posX=0, int posY=0, const Rect *src=nullptr) const override;
 	void draw(SDL_Surface * where, const Rect * dest, const Rect * src) const override;
-	std::shared_ptr<IImage> scaleFast(float scale) const override;
+	std::shared_ptr<IImage> scaleFast(const Point & size) const override;
 	void exportBitmap(const boost::filesystem::path & path) const override;
 	void playerColored(PlayerColor player) override;
 	void setFlagColor(PlayerColor player) override;
@@ -112,6 +112,8 @@ public:
 	void resetPalette(int colorID) override;
 	void resetPalette() override;
 
+	void setAlpha(uint8_t value) override;
+
 	void setSpecialPallete(const SpecialPalette & SpecialPalette) override;
 
 	friend class SDLImageLoader;
@@ -143,6 +145,11 @@ std::shared_ptr<IImage> IImage::createFromFile( const std::string & path )
 	return std::shared_ptr<IImage>(new SDLImage(path));
 }
 
+std::shared_ptr<IImage> IImage::createFromSurface( SDL_Surface * source )
+{
+	return std::shared_ptr<IImage>(new SDLImage(source, true));
+}
+
 // Extremely simple file cache. TODO: smarter, more general solution
 class CFileCache
 {
@@ -679,7 +686,11 @@ void SDLImage::draw(SDL_Surface* where, const Rect * dest, const Rect* src) cons
 	if(dest)
 		destShift += dest->topLeft();
 
-	if(surf->format->BitsPerPixel == 8)
+	uint8_t perSurfaceAlpha;
+	if (SDL_GetSurfaceAlphaMod(surf, &perSurfaceAlpha) != 0)
+		logGlobal->error("SDL_GetSurfaceAlphaMod faied! %s", SDL_GetError());
+
+	if(surf->format->BitsPerPixel == 8 && perSurfaceAlpha == SDL_ALPHA_OPAQUE)
 	{
 		CSDL_Ext::blit8bppAlphaTo24bpp(surf, sourceRect, where, destShift);
 	}
@@ -689,9 +700,12 @@ void SDLImage::draw(SDL_Surface* where, const Rect * dest, const Rect* src) cons
 	}
 }
 
-std::shared_ptr<IImage> SDLImage::scaleFast(float scale) const
+std::shared_ptr<IImage> SDLImage::scaleFast(const Point & size) const
 {
-	auto scaled = CSDL_Ext::scaleSurfaceFast(surf, (int)(surf->w * scale), (int)(surf->h * scale));
+	float scaleX = float(size.x) / width();
+	float scaleY = float(size.y) / height();
+
+	auto scaled = CSDL_Ext::scaleSurfaceFast(surf, (int)(surf->w * scaleX), (int)(surf->h * scaleY));
 
 	if (scaled->format && scaled->format->palette) // fix color keying, because SDL loses it at this point
 		CSDL_Ext::setColorKey(scaled, scaled->format->palette->colors[0]);
@@ -702,11 +716,11 @@ std::shared_ptr<IImage> SDLImage::scaleFast(float scale) const
 
 	SDLImage * ret = new SDLImage(scaled, false);
 
-	ret->fullSize.x = (int) round((float)fullSize.x * scale);
-	ret->fullSize.y = (int) round((float)fullSize.y * scale);
+	ret->fullSize.x = (int) round((float)fullSize.x * scaleX);
+	ret->fullSize.y = (int) round((float)fullSize.y * scaleY);
 
-	ret->margins.x = (int) round((float)margins.x * scale);
-	ret->margins.y = (int) round((float)margins.y * scale);
+	ret->margins.x = (int) round((float)margins.x * scaleX);
+	ret->margins.y = (int) round((float)margins.y * scaleY);
 
 	return std::shared_ptr<IImage>(ret);
 }
@@ -721,6 +735,12 @@ void SDLImage::playerColored(PlayerColor player)
 	graphics->blueToPlayersAdv(surf, player);
 }
 
+void SDLImage::setAlpha(uint8_t value)
+{
+	CSDL_Ext::setAlpha (surf, value);
+	SDL_SetSurfaceBlendMode(surf, SDL_BLENDMODE_BLEND);
+}
+
 void SDLImage::setFlagColor(PlayerColor player)
 {
 	if(player < PlayerColor::PLAYER_LIMIT || player==PlayerColor::NEUTRAL)

+ 7 - 1
client/gui/CAnimation.h

@@ -44,7 +44,7 @@ public:
 	virtual void draw(SDL_Surface * where, int posX = 0, int posY = 0, const Rect * src = nullptr) const = 0;
 	virtual void draw(SDL_Surface * where, const Rect * dest, const Rect * src) const = 0;
 
-	virtual std::shared_ptr<IImage> scaleFast(float scale) const = 0;
+	virtual std::shared_ptr<IImage> scaleFast(const Point & size) const = 0;
 
 	virtual void exportBitmap(const boost::filesystem::path & path) const = 0;
 
@@ -67,6 +67,8 @@ public:
 	virtual void resetPalette(int colorID) = 0;
 	virtual void resetPalette() = 0;
 
+	virtual void setAlpha(uint8_t value) = 0;
+
 	//only indexed bitmaps with 7 special colors
 	virtual void setSpecialPallete(const SpecialPalette & SpecialPalette) = 0;
 
@@ -78,6 +80,10 @@ public:
 
 	/// loads image from specified file. Returns 0-sized images on failure
 	static std::shared_ptr<IImage> createFromFile( const std::string & path );
+
+	/// temporary compatibility method. Creates IImage from existing SDL_Surface
+	/// Surface will be shared, called must still free it with SDL_FreeSurface
+	static std::shared_ptr<IImage> createFromSurface( SDL_Surface * source );
 };
 
 /// Class for handling animation

+ 4 - 1
client/gui/SDL_Extensions.cpp

@@ -852,7 +852,10 @@ void CSDL_Ext::blitSurface(SDL_Surface * src, const Rect & srcRectInput, SDL_Sur
 	SDL_Rect srcRect = CSDL_Ext::toSDL(srcRectInput);
 	SDL_Rect dstRect = CSDL_Ext::toSDL(Rect(dstPoint, srcRectInput.dimensions()));
 
-	SDL_UpperBlit(src, &srcRect, dst, &dstRect);
+	int result = SDL_UpperBlit(src, &srcRect, dst, &dstRect);
+
+	if (result != 0)
+		logGlobal->error("SDL_UpperBlit failed! %s", SDL_GetError());
 }
 
 void CSDL_Ext::blitSurface(SDL_Surface * src, SDL_Surface * dst, const Point & dest)

+ 2 - 2
client/lobby/CBonusSelection.cpp

@@ -525,7 +525,7 @@ void CBonusSelection::CRegion::clickLeft(tribool down, bool previousState)
 	if(indeterminate(down))
 		return;
 
-	if(!down && selectable && !CSDL_Ext::isTransparent(graphicsNotSelected->getSurface(), GH.getCursorPosition() - pos.topLeft()))
+	if(!down && selectable && !graphicsNotSelected->getSurface()->isTransparent(GH.getCursorPosition() - pos.topLeft()))
 	{
 		CSH->setCampaignMap(idOfMapAndRegion);
 	}
@@ -535,7 +535,7 @@ void CBonusSelection::CRegion::clickRight(tribool down, bool previousState)
 {
 	// FIXME: For some reason "down" is only ever contain indeterminate_value
 	auto text = CSH->si->campState->camp->scenarios[idOfMapAndRegion].regionText;
-	if(!CSDL_Ext::isTransparent(graphicsNotSelected->getSurface(), GH.getCursorPosition() - pos.topLeft()) && text.size())
+	if(!graphicsNotSelected->getSurface()->isTransparent(GH.getCursorPosition() - pos.topLeft()) && text.size())
 	{
 		CRClickPopup::createAndPush(text);
 	}

+ 1 - 1
client/mapHandler.cpp

@@ -1434,7 +1434,7 @@ std::shared_ptr<IImage> CMapHandler::CMapCache::requestWorldViewCacheOrCreate(CM
 	auto iter = cache.find(key);
 	if(iter == cache.end())
 	{
-		auto scaled = fullSurface->scaleFast(worldViewCachedScale);
+		auto scaled = fullSurface->scaleFast(fullSurface->dimensions() * worldViewCachedScale);
 		cache[key] = scaled;
 		return scaled;
 	}

+ 17 - 56
client/widgets/Images.cpp

@@ -35,15 +35,14 @@
 #include "../../lib/CGeneralTextHandler.h" //for Unicode related stuff
 #include "../../lib/CRandomGenerator.h"
 
-CPicture::CPicture(SDL_Surface *BG, const Point & position)
-	: bg(BG)
+CPicture::CPicture(std::shared_ptr<IImage> image, const Point & position)
+	: bg(image)
 	, visible(true)
 	, needRefresh(false)
 {
-	BG->refcount += 1;
 	pos += position;
-	pos.w = BG->w;
-	pos.h = BG->h;
+	pos.w = bg->width();
+	pos.h = bg->height();
 }
 
 CPicture::CPicture( const std::string &bmpname, int x, int y )
@@ -55,7 +54,7 @@ CPicture::CPicture( const std::string &bmpname )
 {}
 
 CPicture::CPicture( const std::string &bmpname, const Point & position )
-	: bg(BitmapHandler::loadBitmap(bmpname))
+	: bg(IImage::createFromFile(bmpname))
 	, visible(true)
 	, needRefresh(false)
 {
@@ -65,8 +64,8 @@ CPicture::CPicture( const std::string &bmpname, const Point & position )
 	assert(bg);
 	if(bg)
 	{
-		pos.w = bg->w;
-		pos.h = bg->h;
+		pos.w = bg->width();
+		pos.h = bg->height();
 	}
 	else
 	{
@@ -74,34 +73,14 @@ CPicture::CPicture( const std::string &bmpname, const Point & position )
 	}
 }
 
-CPicture::CPicture(SDL_Surface * BG, const Rect &SrcRect, int x, int y)
-	: CPicture(BG, Point(x,y))
+CPicture::CPicture(std::shared_ptr<IImage> image, const Rect &SrcRect, int x, int y)
+	: CPicture(image, Point(x,y))
 {
 	srcRect = SrcRect;
 	pos.w = srcRect->w;
 	pos.h = srcRect->h;
 }
 
-void CPicture::setSurface(SDL_Surface *to)
-{
-	bg = to;
-	if (srcRect)
-	{
-		pos.w = srcRect->w;
-		pos.h = srcRect->h;
-	}
-	else
-	{
-		pos.w = bg->w;
-		pos.h = bg->h;
-	}
-}
-
-CPicture::~CPicture()
-{
-	SDL_FreeSurface(bg);
-}
-
 void CPicture::show(SDL_Surface * to)
 {
 	if (visible && needRefresh)
@@ -111,41 +90,25 @@ void CPicture::show(SDL_Surface * to)
 void CPicture::showAll(SDL_Surface * to)
 {
 	if(bg && visible)
-	{
-		if(srcRect)
-			CSDL_Ext::blitSurface(bg, *srcRect, to, pos.topLeft());
-		else
-			CSDL_Ext::blitAt(bg, pos, to);
-	}
-}
-
-void CPicture::convertToScreenBPP()
-{
-	SDL_Surface *hlp = bg;
-	bg = SDL_ConvertSurface(hlp,screen->format,0);
-	CSDL_Ext::setDefaultColorKey(bg);
-	SDL_FreeSurface(hlp);
+		bg->draw(to, pos.x, pos.y, srcRect.get_ptr());
 }
 
 void CPicture::setAlpha(int value)
 {
-	CSDL_Ext::setAlpha (bg, value);
-	SDL_SetSurfaceBlendMode(bg,SDL_BLENDMODE_BLEND);
+	bg->setAlpha(value);
 }
 
 void CPicture::scaleTo(Point size)
 {
-	SDL_Surface * scaled = CSDL_Ext::scaleSurface(bg, size.x, size.y);
-
-	SDL_FreeSurface(bg);
+	bg = bg->scaleFast(size);
 
-	setSurface(scaled);
+	pos.w = bg->width();
+	pos.h = bg->height();
 }
 
 void CPicture::colorize(PlayerColor player)
 {
-	assert(bg);
-	graphics->blueToPlayersAdv(bg, player);
+	bg->playerColored(player);
 }
 
 CFilledTexture::CFilledTexture(std::string imageName, Rect position):
@@ -264,7 +227,7 @@ void CAnimImage::showAll(SDL_Surface * to)
 		{
 			if(isScaled())
 			{
-				auto scaled = img->scaleFast(float(scaledSize.x) / img->width());
+				auto scaled = img->scaleFast(scaledSize);
 				scaled->draw(to, pos.x, pos.y);
 			}
 			else
@@ -418,9 +381,7 @@ void CShowableAnim::blitImage(size_t frame, size_t group, SDL_Surface *to)
 	auto img = anim->getImage(frame, group);
 	if(img)
 	{
-		const ColorFilter alphaFilter = ColorFilter::genAlphaShifter(vstd::lerp(0.0f, 1.0f, alpha/255.0f));
-		img->adjustPalette(alphaFilter);
-
+		img->setAlpha(alpha);
 		img->draw(to, pos.x, pos.y, &src);
 	}
 }

+ 6 - 13
client/widgets/Images.h

@@ -26,11 +26,7 @@ class IImage;
 // Image class
 class CPicture : public CIntObject
 {
-	void setSurface(SDL_Surface *to);
-
-	SDL_Surface * bg;
-
-	void convertToScreenBPP();
+	std::shared_ptr<IImage> bg;
 
 public:
 	/// if set, only specified section of internal image will be rendered
@@ -43,25 +39,22 @@ public:
 	/// Deprecated, use CIntObject::disable()/enable() instead
 	bool visible;
 
-	SDL_Surface * getSurface()
+	std::shared_ptr<IImage> getSurface()
 	{
 		return bg;
 	}
 
-	/// wrap existing SDL_Surface
-	/// deprecated, do not use
-	CPicture(SDL_Surface * BG, const Point & position);
+	/// wrap existing image
+	CPicture(std::shared_ptr<IImage> image, const Point & position);
 
-	/// wrap section of existing SDL_Surface
-	CPicture(SDL_Surface *BG, const Rect &SrcRext, int x = 0, int y = 0); //wrap subrect of given surface
+	/// wrap section of an existing Image
+	CPicture(std::shared_ptr<IImage> image, const Rect &SrcRext, int x = 0, int y = 0); //wrap subrect of given surface
 
 	/// Loads image from specified file name
 	CPicture(const std::string & bmpname);
 	CPicture(const std::string & bmpname, const Point & position);
 	CPicture(const std::string & bmpname, int x, int y);
 
-	~CPicture();
-
 	/// set alpha value for whole surface. Note: may be messed up if surface is shared
 	/// 0=transparent, 255=opaque
 	void setAlpha(int value);

+ 1 - 1
client/widgets/TextControls.cpp

@@ -496,7 +496,7 @@ CTextInput::CTextInput(const Rect & Pos, const Point & bgOffset, const std::stri
 #endif
 }
 
-CTextInput::CTextInput(const Rect & Pos, SDL_Surface * srf)
+CTextInput::CTextInput(const Rect & Pos, std::shared_ptr<IImage> srf)
 	:CFocusable(std::make_shared<CKeyboardFocusListener>(this))
 {
 	pos += Pos.topLeft();

+ 2 - 1
client/widgets/TextControls.h

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

+ 4 - 3
client/windows/CWindowObject.cpp

@@ -19,6 +19,7 @@
 #include "../gui/SDL_Extensions.h"
 #include "../gui/CGuiHandler.h"
 #include "../gui/CursorHandler.h"
+#include "../gui/CAnimation.h"
 
 #include "../battle/BattleInterface.h"
 #include "../battle/BattleInterfaceClasses.h"
@@ -213,9 +214,9 @@ void CWindowObject::setShadow(bool on)
 		{
 			OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
 
-			shadowParts.push_back(std::make_shared<CPicture>(shadowCorner, Point(shadowPos.x,   shadowPos.y)));
-			shadowParts.push_back(std::make_shared<CPicture>(shadowRight,  Point(shadowPos.x,   shadowStart.y)));
-			shadowParts.push_back(std::make_shared<CPicture>(shadowBottom, Point(shadowStart.x, shadowPos.y)));
+			shadowParts.push_back(std::make_shared<CPicture>( IImage::createFromSurface(shadowCorner), Point(shadowPos.x,   shadowPos.y)));
+			shadowParts.push_back(std::make_shared<CPicture>( IImage::createFromSurface(shadowRight ),  Point(shadowPos.x,   shadowStart.y)));
+			shadowParts.push_back(std::make_shared<CPicture>( IImage::createFromSurface(shadowBottom), Point(shadowStart.x, shadowPos.y)));
 
 		}
 		SDL_FreeSurface(shadowCorner);