source/code/CppSdlImageHolder.cpp
browsing at commit = b1592756a4aa5daff85e294335c505bfa59f834c
/*
===========================================================================
blockattack - Block Attack - Rise of the Blocks
Copyright (C) 2005-2013 Poul Sander
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/
Source information and contacts persons can be found at
http://blockattack.sf.net
===========================================================================
*/
#include "CppSdlImageHolder.hpp"
#include "SDL_image.h"
namespace CppSdl
{
CppSdlImageHolder::CppSdlImageHolder()
{
data = NULL;
counter = new int;
(*counter)=1;
}
CppSdlImageHolder::CppSdlImageHolder(std::string filename)
{
data = IMG_Load(filename.c_str());
if(!data)
{
//Here we should throw an exception
CppSdlException e(IMAGE,CPPSDL_ERROR_MISSINGFILE,"Could not read file \""+filename+"\"");
throw e;
}
SDL_GetClipRect(data,&area);
OptimizeForBlit();
counter = new int;
*counter=1;
}
CppSdlImageHolder::CppSdlImageHolder(const CppSdlImageHolder& orig)
{
//Just take the data from the original. This is technically wrong but adds a little performance.
data = orig.data;
area = orig.area;
if(orig.counter)
{
counter = orig.counter;
(*counter)++;
}
}
CppSdlImageHolder& CppSdlImageHolder::operator =(const CppSdlImageHolder& rhs)
{
// Check for self-assignment!
if (this == &rhs) // Same object?
return *this; // Yes, so skip assignment, and just return *this.
MakeNull();
data = rhs.data;
area = rhs.area;
if(rhs.counter)
{
counter = rhs.counter;
(*counter)++;
}
return *this;
}
CppSdlImageHolder::CppSdlImageHolder(char* rawdata, int datasize)
{
SDL_RWops *rw = SDL_RWFromMem (rawdata, datasize);
//The above might fail and return null.
if(!rw)
{
CppSdlException e(IMAGE,CPPSDL_ERROR_NULLPOINTER, "Could not read raw data");
throw e;
}
data = IMG_Load_RW(rw,true); //the second argument tells the function to free RWops
if(!data)
{
CppSdlException e(IMAGE,CPPSDL_ERROR_DATA,"Could not convert raw data to image");
throw e;
}
SDL_GetClipRect(data,&area);
OptimizeForBlit();
counter = new int;
*counter = 1;
}
CppSdlImageHolder::~CppSdlImageHolder()
{
if(!counter)
return; //There are no counter, so already freed
MakeNull();
if(*counter == 0)
{
delete counter;
counter = NULL;
}
}
SDL_Surface* CppSdlImageHolder::GetRawDataInsecure()
{
Initialized();
return data;
}
Uint32 CppSdlImageHolder::GetWidth()
{
if(IsNull())
return 0;
return area.w;
}
Uint32 CppSdlImageHolder::GetHeight()
{
if(IsNull())
return 0;
return area.h;
}
void CppSdlImageHolder::Cut(Uint32 x, Uint32 y, Sint32 w = -1, Sint32 h = -1)
{
Initialized();
if(w<0)
{
w = GetWidth() - x;
}
if(h<0)
{
h = GetHeight() - y;
}
if(x+w>GetWidth())
{
//throw exception
}
if(y+h>GetHeight())
{
//throw exception
}
if(x<0 || x>GetWidth())
{
//throw exception
}
if(y<0 || y>GetHeight())
{
//throw exception
}
area.x += x;
area.y += y;
area.w = w;
area.h = h;
}
void CppSdlImageHolder::PaintTo(SDL_Surface* target, int x, int y)
{
static SDL_Rect dest; //static for reuse
if(IsNull())
return;
dest.x = x;
dest.y = y;
SDL_BlitSurface(data,&area, target,&dest);
}
void CppSdlImageHolder::OptimizeForBlit(bool allowAlpha)
{
static SDL_Surface *tmp;
Initialized();
if(allowAlpha)
tmp = SDL_DisplayFormatAlpha(data);
else
tmp = SDL_DisplayFormat(data);
SDL_FreeSurface(data);
data = tmp;
}
void CppSdlImageHolder::Initialized()
{
if(data == NULL)
throw(CppSdlException(IMAGE,CPPSDL_ERROR_NULLPOINTER,"ImageHolder used uninitialized!"));
}
bool CppSdlImageHolder::IsNull()
{
if(data == NULL || counter == NULL)
return true;
else
return false;
}
void CppSdlImageHolder::MakeNull()
{
if(IsNull())
return;
(*counter)--;
if(*counter == 0 && data != NULL)
{
SDL_FreeSurface(data);
data = NULL;
}
}
}