2010-02-04 13:33:47 +02:00
|
|
|
/***************************************************************************
|
2011-10-23 17:43:56 +03:00
|
|
|
* Copyright (C) 2006 by Massimiliano Torromeo *
|
|
|
|
* massimiliano.torromeo@gmail.com *
|
2010-02-04 13:33:47 +02:00
|
|
|
* *
|
|
|
|
* 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, write to the *
|
|
|
|
* Free Software Foundation, Inc., *
|
|
|
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
|
|
***************************************************************************/
|
|
|
|
|
2011-03-30 04:21:31 +03:00
|
|
|
#include "surface.h"
|
2011-10-23 17:43:56 +03:00
|
|
|
|
2011-03-30 04:21:31 +03:00
|
|
|
#include "debug.h"
|
2011-10-23 17:43:56 +03:00
|
|
|
#include "imageio.h"
|
2011-04-01 19:31:54 +03:00
|
|
|
#include "surfacecollection.h"
|
2011-10-23 17:43:56 +03:00
|
|
|
#include "utilities.h"
|
2011-03-30 04:21:31 +03:00
|
|
|
|
2010-02-04 13:33:47 +02:00
|
|
|
#include <SDL_gfxPrimitives.h>
|
|
|
|
|
|
|
|
#include <iostream>
|
2011-10-23 17:43:56 +03:00
|
|
|
|
2010-02-04 13:33:47 +02:00
|
|
|
using namespace std;
|
|
|
|
|
2010-05-02 15:29:09 +03:00
|
|
|
RGBAColor strtorgba(const string &strColor) {
|
2010-02-04 13:33:47 +02:00
|
|
|
RGBAColor c = {0,0,0,255};
|
|
|
|
c.r = constrain( strtol( strColor.substr(0,2).c_str(), NULL, 16 ), 0, 255 );
|
|
|
|
c.g = constrain( strtol( strColor.substr(2,2).c_str(), NULL, 16 ), 0, 255 );
|
|
|
|
c.b = constrain( strtol( strColor.substr(4,2).c_str(), NULL, 16 ), 0, 255 );
|
|
|
|
c.a = constrain( strtol( strColor.substr(6,2).c_str(), NULL, 16 ), 0, 255 );
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
2011-06-02 18:59:26 +03:00
|
|
|
Surface *Surface::openOutputSurface(int width, int height, int bitsperpixel) {
|
|
|
|
SDL_ShowCursor(SDL_DISABLE);
|
|
|
|
SDL_Surface *raw = SDL_SetVideoMode(
|
|
|
|
width, height, bitsperpixel, SDL_HWSURFACE | SDL_DOUBLEBUF);
|
|
|
|
return raw ? new Surface(raw, false) : NULL;
|
|
|
|
}
|
|
|
|
|
2011-06-03 12:46:36 +03:00
|
|
|
Surface *Surface::emptySurface(int width, int height) {
|
|
|
|
SDL_Surface *raw = SDL_CreateRGBSurface(
|
|
|
|
SDL_SWSURFACE, width, height, 32, 0, 0, 0, 0);
|
|
|
|
if (!raw) return NULL;
|
|
|
|
SDL_FillRect(raw, NULL, SDL_MapRGB(raw->format, 0, 0, 0));
|
|
|
|
return new Surface(raw, true);
|
|
|
|
}
|
|
|
|
|
2011-06-02 23:09:03 +03:00
|
|
|
Surface *Surface::loadImage(const string &img, const string &skin) {
|
|
|
|
string skinpath;
|
2011-07-11 12:19:18 +03:00
|
|
|
if (!skin.empty() && !img.empty() && img[0]!='/')
|
|
|
|
skinpath = SurfaceCollection::getSkinFilePath(skin, img);
|
|
|
|
else
|
|
|
|
skinpath = img;
|
2011-06-02 23:09:03 +03:00
|
|
|
|
|
|
|
SDL_Surface *raw = loadPNG(skinpath);
|
|
|
|
if (!raw) {
|
|
|
|
ERROR("Couldn't load surface '%s'\n", img.c_str());
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return new Surface(raw, true);
|
|
|
|
}
|
|
|
|
|
2011-06-02 18:59:26 +03:00
|
|
|
Surface::Surface(SDL_Surface *raw_, bool freeWhenDone_)
|
|
|
|
: raw(raw_)
|
|
|
|
, freeWhenDone(freeWhenDone_)
|
|
|
|
{
|
2011-06-02 23:09:03 +03:00
|
|
|
halfW = raw->w/2;
|
|
|
|
halfH = raw->h/2;
|
2010-02-04 13:33:47 +02:00
|
|
|
}
|
|
|
|
|
2011-06-02 05:57:21 +03:00
|
|
|
Surface::Surface(Surface *s) {
|
2011-06-03 12:46:36 +03:00
|
|
|
raw = SDL_ConvertSurface(s->raw, s->raw->format, SDL_SWSURFACE);
|
2011-06-05 06:27:28 +03:00
|
|
|
// Note: A bug in SDL_ConvertSurface() leaves the per-surface alpha
|
|
|
|
// undefined when converting from RGBA to RGBA. This can cause
|
|
|
|
// problems if the surface is later converted to a format without
|
|
|
|
// an alpha channel, such as the display format.
|
|
|
|
raw->format->alpha = s->raw->format->alpha;
|
2011-06-02 19:07:17 +03:00
|
|
|
freeWhenDone = true;
|
2010-02-04 13:33:47 +02:00
|
|
|
halfW = raw->w/2;
|
|
|
|
halfH = raw->h/2;
|
|
|
|
}
|
|
|
|
|
|
|
|
Surface::~Surface() {
|
2011-06-02 18:59:26 +03:00
|
|
|
if (freeWhenDone) {
|
|
|
|
SDL_FreeSurface(raw);
|
|
|
|
}
|
2010-02-04 13:33:47 +02:00
|
|
|
}
|
|
|
|
|
2011-06-03 12:46:36 +03:00
|
|
|
void Surface::convertToDisplayFormat() {
|
|
|
|
SDL_Surface *newSurface = SDL_DisplayFormat(raw);
|
|
|
|
if (newSurface) {
|
|
|
|
if (freeWhenDone) {
|
|
|
|
SDL_FreeSurface(raw);
|
|
|
|
}
|
|
|
|
raw = newSurface;
|
|
|
|
freeWhenDone = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-04 13:33:47 +02:00
|
|
|
void Surface::flip() {
|
2011-06-02 18:59:26 +03:00
|
|
|
SDL_Flip(raw);
|
2010-02-04 13:33:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Surface::blit(SDL_Surface *destination, int x, int y, int w, int h, int a) {
|
|
|
|
if (destination == NULL || a==0) return false;
|
|
|
|
|
2012-04-11 00:01:16 +03:00
|
|
|
SDL_Rect src = { 0, 0, static_cast<Uint16>(w), static_cast<Uint16>(h) };
|
2010-02-04 13:33:47 +02:00
|
|
|
SDL_Rect dest;
|
|
|
|
dest.x = x;
|
|
|
|
dest.y = y;
|
|
|
|
if (a>0 && a!=raw->format->alpha)
|
|
|
|
SDL_SetAlpha(raw, SDL_SRCALPHA|SDL_RLEACCEL, a);
|
|
|
|
return SDL_BlitSurface(raw, (w==0 || h==0) ? NULL : &src, destination, &dest);
|
|
|
|
}
|
|
|
|
bool Surface::blit(Surface *destination, int x, int y, int w, int h, int a) {
|
|
|
|
return blit(destination->raw,x,y,w,h,a);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Surface::blitCenter(SDL_Surface *destination, int x, int y, int w, int h, int a) {
|
|
|
|
int oh, ow;
|
|
|
|
if (w==0) ow = halfW; else ow = min(halfW,w/2);
|
|
|
|
if (h==0) oh = halfH; else oh = min(halfH,h/2);
|
|
|
|
return blit(destination,x-ow,y-oh,w,h,a);
|
|
|
|
}
|
|
|
|
bool Surface::blitCenter(Surface *destination, int x, int y, int w, int h, int a) {
|
|
|
|
return blitCenter(destination->raw,x,y,w,h,a);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Surface::blitRight(SDL_Surface *destination, int x, int y, int w, int h, int a) {
|
|
|
|
if (!w) w = raw->w;
|
|
|
|
return blit(destination,x-min(raw->w,w),y,w,h,a);
|
|
|
|
}
|
|
|
|
bool Surface::blitRight(Surface *destination, int x, int y, int w, int h, int a) {
|
|
|
|
if (!w) w = raw->w;
|
|
|
|
return blitRight(destination->raw,x,y,w,h,a);
|
|
|
|
}
|
|
|
|
|
2012-04-10 23:33:43 +03:00
|
|
|
int Surface::box(Sint16 x, Sint16 y, Uint16 w, Uint16 h, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
|
|
|
|
return boxRGBA(raw, x, y, x + w - 1, y + h - 1, r, g, b, a);
|
2010-02-04 13:33:47 +02:00
|
|
|
}
|
2012-04-10 23:33:43 +03:00
|
|
|
int Surface::box(Sint16 x, Sint16 y, Uint16 w, Uint16 h, Uint8 r, Uint8 g, Uint8 b) {
|
|
|
|
SDL_Rect re = { x, y, w, h };
|
|
|
|
return SDL_FillRect(raw, &re, SDL_MapRGBA(raw->format, r, g, b, 255));
|
2010-02-04 13:33:47 +02:00
|
|
|
}
|
2012-04-10 23:33:43 +03:00
|
|
|
int Surface::box(Sint16 x, Sint16 y, Uint16 w, Uint16 h, RGBAColor c) {
|
|
|
|
return box(x, y, w, h, c.r, c.g, c.b, c.a);
|
2010-02-04 13:33:47 +02:00
|
|
|
}
|
|
|
|
int Surface::box(SDL_Rect re, RGBAColor c) {
|
2011-06-02 04:39:34 +03:00
|
|
|
return boxRGBA(
|
|
|
|
raw, re.x, re.y, re.x + re.w - 1, re.y + re.h - 1, c.r, c.g, c.b, c.a
|
|
|
|
);
|
2010-02-04 13:33:47 +02:00
|
|
|
}
|
|
|
|
|
2012-04-10 23:33:43 +03:00
|
|
|
int Surface::rectangle(Sint16 x, Sint16 y, Uint16 w, Uint16 h, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
|
|
|
|
return rectangleRGBA(raw, x, y, x + w - 1, y + h - 1, r, g, b, a);
|
2010-02-04 13:33:47 +02:00
|
|
|
}
|
2012-04-10 23:33:43 +03:00
|
|
|
int Surface::rectangle(Sint16 x, Sint16 y, Uint16 w, Uint16 h, RGBAColor c) {
|
|
|
|
return rectangle(x, y, w, h, c.r, c.g, c.b, c.a);
|
2010-02-04 13:33:47 +02:00
|
|
|
}
|
|
|
|
int Surface::rectangle(SDL_Rect re, RGBAColor c) {
|
2012-04-10 23:33:43 +03:00
|
|
|
return rectangle(re.x, re.y, re.w, re.h, c.r, c.g, c.b, c.a);
|
2010-02-04 13:33:47 +02:00
|
|
|
}
|
|
|
|
|
2012-04-10 23:33:43 +03:00
|
|
|
int Surface::hline(Sint16 x, Sint16 y, Uint16 w, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
|
|
|
|
return hlineRGBA(raw, x, x + w - 1, y, r, g, b, a);
|
2010-02-04 13:33:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Surface::clearClipRect() {
|
|
|
|
SDL_SetClipRect(raw,NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Surface::setClipRect(int x, int y, int w, int h) {
|
2012-04-11 00:01:16 +03:00
|
|
|
SDL_Rect rect = {
|
|
|
|
static_cast<Sint16>(x), static_cast<Sint16>(y),
|
|
|
|
static_cast<Uint16>(w), static_cast<Uint16>(h)
|
|
|
|
};
|
2010-02-04 13:33:47 +02:00
|
|
|
setClipRect(rect);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Surface::setClipRect(SDL_Rect rect) {
|
|
|
|
SDL_SetClipRect(raw,&rect);
|
|
|
|
}
|
|
|
|
|
2013-08-03 23:30:12 +03:00
|
|
|
bool Surface::blit(Surface *destination, SDL_Rect container, Font::HAlign halign, Font::VAlign valign) {
|
2010-02-04 13:33:47 +02:00
|
|
|
switch (halign) {
|
2013-08-03 23:30:12 +03:00
|
|
|
case Font::HAlignLeft:
|
2011-05-09 06:17:25 +03:00
|
|
|
break;
|
2013-08-03 23:30:12 +03:00
|
|
|
case Font::HAlignCenter:
|
2010-02-04 13:33:47 +02:00
|
|
|
container.x += container.w/2-halfW;
|
|
|
|
break;
|
2013-08-03 23:30:12 +03:00
|
|
|
case Font::HAlignRight:
|
2010-02-04 13:33:47 +02:00
|
|
|
container.x += container.w-raw->w;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (valign) {
|
2013-08-03 23:30:12 +03:00
|
|
|
case Font::VAlignTop:
|
2011-05-09 06:17:25 +03:00
|
|
|
break;
|
2013-08-03 23:30:12 +03:00
|
|
|
case Font::VAlignMiddle:
|
2010-02-04 13:33:47 +02:00
|
|
|
container.y += container.h/2-halfH;
|
|
|
|
break;
|
2013-08-03 23:30:12 +03:00
|
|
|
case Font::VAlignBottom:
|
2010-02-04 13:33:47 +02:00
|
|
|
container.y += container.h-raw->h;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return blit(destination,container.x,container.y);
|
|
|
|
}
|