1
0
mirror of git://projects.qi-hardware.com/gmenu2x.git synced 2024-11-17 01:11:53 +02:00
gmenu2x/src/surface.cpp

364 lines
10 KiB
C++
Raw Normal View History

/***************************************************************************
* Copyright (C) 2006 by Massimiliano Torromeo *
* massimiliano.torromeo@gmail.com *
* *
* 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. *
***************************************************************************/
#include "surface.h"
#include "imageio.h"
#include "utilities.h"
#include "debug.h"
#include <SDL_gfxPrimitives.h>
#include <iostream>
using namespace std;
RGBAColor strtorgba(const string &strColor) {
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;
}
Surface::Surface() {
raw = NULL;
dblbuffer = NULL;
}
Surface::Surface(const string &img, bool alpha, const string &skin) {
raw = NULL;
dblbuffer = NULL;
load(img, alpha, skin);
halfW = raw->w/2;
halfH = raw->h/2;
}
Surface::Surface(const string &img, const string &skin, bool alpha) {
raw = NULL;
dblbuffer = NULL;
load(img, alpha, skin);
halfW = raw->w/2;
halfH = raw->h/2;
}
Surface::Surface(SDL_Surface *s, SDL_PixelFormat *fmt, Uint32 flags) {
dblbuffer = NULL;
this->operator =(s);
if (fmt!=NULL || flags!=0) {
if (fmt==NULL) fmt = s->format;
if (flags==0) flags = s->flags;
raw = SDL_ConvertSurface( s, fmt, flags );
}
}
Surface::Surface(Surface *s) {
dblbuffer = NULL;
this->operator =(s->raw);
}
Surface::Surface(int w, int h, Uint32 flags) {
dblbuffer = NULL;
Uint32 rmask, gmask, bmask, amask;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
rmask = 0xff000000;
gmask = 0x00ff0000;
bmask = 0x0000ff00;
amask = 0x000000ff;
#else
rmask = 0x000000ff;
gmask = 0x0000ff00;
bmask = 0x00ff0000;
amask = 0xff000000;
#endif
raw = SDL_CreateRGBSurface( flags, w, h, 16, rmask, gmask, bmask, amask );
halfW = w/2;
halfH = h/2;
}
Surface::~Surface() {
free();
}
void Surface::enableVirtualDoubleBuffer(SDL_Surface *surface) {
dblbuffer = surface;
raw = SDL_DisplayFormat(dblbuffer);
}
void Surface::free() {
if (raw!=NULL) SDL_FreeSurface( raw );
if (dblbuffer!=NULL) SDL_FreeSurface( dblbuffer );
}
SDL_PixelFormat *Surface::format() {
if (raw==NULL)
return NULL;
else
return raw->format;
}
void Surface::load(const string &img, bool alpha, const string &skin) {
free();
string skinpath;
if (!skin.empty() && !img.empty() && img[0]!='/') {
skinpath = "skins/"+skin+"/"+img;
if (!fileExists(skinpath))
skinpath = "skins/Default/"+img;
} else {
skinpath = img;
}
SDL_Surface *buf = loadPNG(skinpath);
if (buf!=NULL) {
if (alpha)
raw = SDL_DisplayFormatAlpha(buf);
else
raw = SDL_DisplayFormat(buf);
SDL_FreeSurface(buf);
} else {
ERROR("Couldn't load surface '%s'\n", img.c_str());
}
}
void Surface::lock() {
if ( SDL_MUSTLOCK(raw) && !locked ) {
if ( SDL_LockSurface(raw) < 0 ) {
ERROR("Can't lock surface: '%s'\n", SDL_GetError());
SDL_Quit();
}
locked = true;
}
}
void Surface::unlock() {
if ( SDL_MUSTLOCK(raw) && locked ) {
SDL_UnlockSurface(raw);
locked = false;
}
}
void Surface::flip() {
if (dblbuffer!=NULL) {
this->blit(dblbuffer,0,0);
SDL_Flip(dblbuffer);
} else {
SDL_Flip(raw);
}
}
bool Surface::blit(SDL_Surface *destination, int x, int y, int w, int h, int a) {
if (destination == NULL || a==0) return false;
SDL_Rect src = {0,0,w,h};
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);
}
void Surface::putPixel(int x, int y, SDL_Color color) {
putPixel(x,y, SDL_MapRGB( raw->format , color.r , color.g , color.b ));
}
void Surface::putPixel(int x, int y, Uint32 color) {
//determine position
char* pPosition = ( char* ) raw->pixels ;
//offset by y
pPosition += ( raw->pitch * y ) ;
//offset by x
pPosition += ( raw->format->BytesPerPixel * x ) ;
//copy pixel data
memcpy ( pPosition , &color , raw->format->BytesPerPixel ) ;
}
SDL_Color Surface::pixelColor(int x, int y) {
SDL_Color color;
Uint32 col = pixel(x,y);
SDL_GetRGB( col, raw->format, &color.r, &color.g, &color.b );
return color;
}
Uint32 Surface::pixel(int x, int y) {
//determine position
char* pPosition = ( char* ) raw->pixels ;
//offset by y
pPosition += ( raw->pitch * y ) ;
//offset by x
pPosition += ( raw->format->BytesPerPixel * x ) ;
//copy pixel data
Uint32 col = 0;
memcpy ( &col , pPosition , raw->format->BytesPerPixel ) ;
return col;
}
void Surface::blendAdd(Surface *target, int x, int y) {
SDL_Color targetcol, blendcol;
for (int iy=0; iy<raw->h; iy++)
if (iy+y >= 0 && iy+y < target->raw->h)
for (int ix=0; ix<raw->w; ix++) {
if (ix+x >= 0 && ix+x < target->raw->w) {
blendcol = pixelColor(ix,iy);
targetcol = target->pixelColor(ix+x,iy+y);
targetcol.r = min(targetcol.r+blendcol.r, 255);
targetcol.g = min(targetcol.g+blendcol.g, 255);
targetcol.b = min(targetcol.b+blendcol.b, 255);
target->putPixel(ix+x,iy+y,targetcol);
}
}
/*
Uint32 bcol, tcol;
char *pPos, *tpPos;
for (int iy=0; iy<raw->h; iy++)
if (iy+y >= 0 && iy+y < target->raw->h) {
pPos = (char*)raw->pixels + raw->pitch*iy;
tpPos = (char*)target->raw->pixels + target->raw->pitch*(iy+y);
for (int ix=0; ix<raw->w; ix++) {
memcpy(&bcol, pPos, raw->format->BytesPerPixel);
memcpy(&tcol, tpPos, target->raw->format->BytesPerPixel);
//memcpy(tpPos, &bcol, target->raw->format->BytesPerPixel);
pPos += raw->format->BytesPerPixel;
tpPos += target->raw->format->BytesPerPixel;
target->putPixel(ix+x,iy+y,bcol);
}
}
*/
}
void Surface::write(ASFont *font, const string &text, int x, int y, const unsigned short halign, const unsigned short valign) {
font->write(this,text,x,y,halign,valign);
}
void Surface::operator = (SDL_Surface *s) {
raw = SDL_DisplayFormat(s);
halfW = raw->w/2;
halfH = raw->h/2;
}
void Surface::operator = (Surface *s) {
this->operator =(s->raw);
}
int Surface::box(Sint16 x, Sint16 y, Sint16 w, Sint16 h, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
return boxRGBA(raw,x,y,x+w-1,y+h-1,r,g,b,a);
}
int Surface::box(SDL_Rect re, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
return boxRGBA(raw,re.x,re.y,re.x+re.w-1,re.y+re.h-1,r,g,b,a);
}
int Surface::box(SDL_Rect re, Uint8 r, Uint8 g, Uint8 b) {
return SDL_FillRect(raw, &re, SDL_MapRGBA(format(),r,g,b,255));
}
int Surface::box(Sint16 x, Sint16 y, Sint16 w, Sint16 h, Uint8 r, Uint8 g, Uint8 b) {
SDL_Rect re = {x,y,w,h};
return box(re,r,g,b);
}
int Surface::box(Sint16 x, Sint16 y, Sint16 w, Sint16 h, RGBAColor c) {
return box(x,y,w,h,c.r,c.g,c.b,c.a);
}
int Surface::box(SDL_Rect re, RGBAColor c) {
return box(re,c.r,c.g,c.b,c.a);
}
int Surface::rectangle(Sint16 x, Sint16 y, Sint16 w, Sint16 h, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
return rectangleRGBA(raw,x,y,x+w-1,y+h-1,r,g,b,a);
}
int Surface::rectangle(SDL_Rect re, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
return rectangleRGBA(raw,re.x,re.y,re.x+re.w-1,re.y+re.h-1,r,g,b,a);
}
int Surface::rectangle(Sint16 x, Sint16 y, Sint16 w, Sint16 h, Uint8 r, Uint8 g, Uint8 b) {
return rectangleColor(raw, x,y,x+w-1,y+h-1, SDL_MapRGBA(format(),r,g,b,255));
}
int Surface::rectangle(SDL_Rect re, Uint8 r, Uint8 g, Uint8 b) {
return rectangleColor(raw, re.x,re.y,re.x+re.w-1,re.y+re.h-1, SDL_MapRGBA(format(),r,g,b,255));
}
int Surface::rectangle(Sint16 x, Sint16 y, Sint16 w, Sint16 h, RGBAColor c) {
return rectangle(x,y,w,h,c.r,c.g,c.b,c.a);
}
int Surface::rectangle(SDL_Rect re, RGBAColor c) {
return rectangle(re.x,re.y,re.w,re.h,c.r,c.g,c.b,c.a);
}
int Surface::hline(Sint16 x, Sint16 y, Sint16 w, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
return hlineRGBA(raw,x,x+w-1,y,r,g,b,a);
}
int Surface::hline(Sint16 x, Sint16 y, Sint16 w, RGBAColor c) {
return hline(x,y,w-1,c.r,c.g,c.b,c.a);
}
void Surface::clearClipRect() {
SDL_SetClipRect(raw,NULL);
}
void Surface::setClipRect(int x, int y, int w, int h) {
SDL_Rect rect = {x,y,w,h};
setClipRect(rect);
}
void Surface::setClipRect(SDL_Rect rect) {
SDL_SetClipRect(raw,&rect);
}
bool Surface::blit(Surface *destination, SDL_Rect container, const unsigned short halign, const unsigned short valign) {
switch (halign) {
case SFontHAlignCenter:
container.x += container.w/2-halfW;
break;
case SFontHAlignRight:
container.x += container.w-raw->w;
break;
}
switch (valign) {
case SFontVAlignMiddle:
container.y += container.h/2-halfH;
break;
case SFontVAlignBottom:
container.y += container.h-raw->h;
break;
}
return blit(destination,container.x,container.y);
}