SDLGameEngine

src/sgegfx.c

00001 /*
00002  * Copyright (c) 2007 Heiko Irrgang
00003  *
00004  * The license and distribution terms for this file may be
00005  * found in the file COPYING in this distribution or at
00006  * http://93-interactive.com/cms/products/software/sdl-game-engine/license/
00007  */
00008 
00009 #include <sge.h>
00010 
00011 SGEPOSITION *sgePositionNew(int x, int y) {
00012         SGEPOSITION *ret;
00013 
00014         sgeNew(ret, SGEPOSITION);
00015         ret->x=x;
00016         ret->y=y;
00017         return ret;
00018 }
00019 
00020 void sgePositionDestroy(SGEPOSITION *p) {
00021         sgeFree(p);
00022 }
00023 
00024 SGEPIXELINFO *sgePixelInfoNew(Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
00025         SGEPIXELINFO *ret;
00026 
00027         sgeNew(ret, SGEPIXELINFO);
00028         ret->r=r;
00029         ret->g=g;
00030         ret->b=b;
00031         ret->a=a;
00032 
00033         return ret;
00034 }
00035 
00036 void sgePixelInfoDestroy(SGEPIXELINFO *i) {
00037         sgeFree(i);
00038 }
00039 
00040 inline Uint32 sgeMakeColor(SDL_Surface *surface, int r, int g, int b, int a) {
00041         Uint32 color;
00042         if (a<0) {
00043                 color=SDL_MapRGB(surface->format,r,g,b);
00044         } else {
00045                 color=SDL_MapRGBA(surface->format,r,g,b,a);
00046         }
00047         return color;
00048 }
00049 
00050 inline void sgeFillRect(SDL_Surface *dest, int x, int y, int w, int h, Uint32 color) {
00051         SDL_Rect rect;
00052         rect.x=x;
00053         rect.y=y;
00054         rect.w=w;
00055         rect.h=h;
00056         SDL_FillRect(dest, &rect, color);
00057 }
00058 
00059 inline void sgeDrawRect(SDL_Surface *dest, int x, int y, int w, int h, int linewidth, Uint32 color) {
00060         sgeFillRect(dest, x, y, w, linewidth, color);
00061         sgeFillRect(dest, x, y, linewidth, h, color);
00062         sgeFillRect(dest, x+w-linewidth, y, linewidth, h, color);
00063         sgeFillRect(dest, x, y+h-linewidth, w, linewidth, color);
00064 }
00065 
00066 inline void sgeDrawPixel(SDL_Surface *dest, int x, int y, Uint32 color) {
00067         Uint8 *buf8=NULL;
00068         Uint16 *buf16=NULL;
00069         Uint32 *buf32=NULL;
00070 
00071         if (x<0 || y<0) return;
00072         if (x>=dest->w || y>=dest->h) return;
00073 
00074         switch (dest->format->BitsPerPixel) {
00075                 case 8:
00076                         buf8=(Uint8 *)dest->pixels+y*dest->w+x;
00077                         *buf8=(Uint8)color;
00078                         break;
00079                 case 16:
00080                         buf16=(Uint16 *)dest->pixels+y*dest->w+x;
00081                         *buf16=(Uint16)color;
00082                         break;
00083                 default:
00084                         buf32=(Uint32 *)dest->pixels+y*dest->w+x;
00085                         *buf32=color;
00086                         break;
00087         }
00088 }
00089 
00090 inline SGEPIXELINFO *sgeGetPixel(SDL_Surface *dest, int x, int y) {
00091         Uint8 p8, *buf8;
00092         Uint16 p16, *buf16;
00093         Uint32 p32, *buf32;
00094         SGEPIXELINFO *ret;
00095 
00096         switch (dest->format->BitsPerPixel) {
00097                 case 8:
00098                         buf8=(Uint8 *)dest->pixels;
00099                         p8=buf8[y*dest->w+x];
00100                         p32=p8;
00101                         break;
00102                 case 16:
00103                         buf16=(Uint16 *)dest->pixels;
00104                         p16=buf16[y*dest->w+x];
00105                         p32=p16;
00106                         break;
00107                 default:
00108                         buf32=(Uint32 *)dest->pixels;
00109                         p32=buf32[y*dest->w+x];
00110                         break;
00111         }
00112         sgeNew(ret, SGEPIXELINFO);
00113         SDL_GetRGBA(p32, dest->format, &ret->r, &ret->g, &ret->b, &ret->a);
00114         return ret;
00115 }
00116 
00117 inline void sgeDrawLine(SDL_Surface *dest, int x, int y, int x2, int y2, Uint32 color) {
00118         int steep=0;
00119         int tmp=0;
00120         int dx=0;
00121         int dy=0;
00122         int err=0;
00123         int ystep=1;
00124         int yy=0;
00125         int xx=0;
00126 
00127         if (abs(y2-y)>abs(x2-x)) steep=1;
00128         if (steep) {
00129                 tmp=x;
00130                 x=y;
00131                 y=tmp;
00132                 tmp=x2;
00133                 x2=y2;
00134                 y2=tmp;
00135         }
00136         if (x>x2) {
00137                 tmp=x;
00138                 x=x2;
00139                 x2=tmp;
00140                 tmp=y;
00141                 y=y2;
00142                 y2=tmp;
00143         }
00144         
00145         if (y>y2) {
00146                 ystep=-1;
00147         }
00148 
00149         dx=x2-x;
00150         dy=abs(y2-y);
00151         err=-dx>>1;
00152         yy=y;
00153         
00154         for (xx=x;xx<=x2;xx++) {
00155                 if (!steep) {
00156                         sgeDrawPixel(dest, xx, yy, color);
00157                 } else {
00158                         sgeDrawPixel(dest, yy, xx, color);
00159                 }
00160                 err+=dy;
00161                 if (err>0) {
00162                         yy+=ystep;
00163                         err-=dx;
00164                 }
00165         }
00166 }
00167 
00168 inline void sgeDrawImage(SDL_Surface *dest, SDL_Surface *image, int x, int y) {
00169         SDL_Rect r;
00170         r.w=image->w;
00171         r.h=image->h;
00172         r.x=x;
00173         r.y=y;
00174         SDL_BlitSurface(image, NULL, dest, &r);
00175 }
00176 
00177 void sgeIgnoreAlpha(SDL_Surface *s) {
00178         SDL_SetAlpha(s, s->flags^SDL_SRCALPHA, SDL_ALPHA_OPAQUE);
00179 }
00180 
00181 void sgeUseAlpha(SDL_Surface *s) {
00182         SDL_SetAlpha(s, SDL_SRCALPHA, SDL_ALPHA_OPAQUE);
00183 }
00184 
00185 SDL_Surface *sgeRotoZoom(SDL_Surface *source, float rotation, float zoom) {
00186         Uint32 *src32=(Uint32*)source->pixels;
00187         Uint16 *src16=(Uint16*)source->pixels;
00188         Uint8 *src8=(Uint8*)source->pixels;
00189         SDL_Surface *ret;
00190         SDL_Surface *target=SDL_CreateRGBSurface(
00191                         source->flags,
00192                         (int)((float)source->w*zoom)*3,
00193                         (int)((float)source->h*zoom)<<1,
00194                         source->format->BitsPerPixel,
00195                         source->format->Rmask,
00196                         source->format->Gmask,
00197                         source->format->Bmask,
00198                         source->format->Amask
00199         );
00200         SDL_Rect r;
00201         Uint32 *dst32=(Uint32*)target->pixels;
00202         Uint16 *dst16=(Uint16*)target->pixels;
00203         Uint8 *dst8=(Uint8*)target->pixels;
00204 
00205         int sinfp=(int)((sin(rotation)*65536.0)/zoom);
00206         int cosfp=(int)((cos(rotation)*65536.0)/zoom);
00207 
00208         int xc;
00209         int yc;
00210 
00211         int tx,ty;
00212         int x,y;
00213         int tempx,tempy;
00214 
00215         int targetpitch;
00216         int sourcepitch;
00217         int divider;
00218 
00219         int minx=target->w;
00220         int miny=target->h;
00221         int maxx=0;
00222         int maxy=0;
00223 
00224         switch (source->format->BitsPerPixel) {
00225                 case 8:
00226                         divider=0;
00227                         break;
00228                 case 16:
00229                         divider=1;
00230                         break;
00231                 default:
00232                         divider=2;
00233                         break;
00234         }
00235 
00236         targetpitch=target->pitch>>divider;
00237         sourcepitch=source->pitch>>divider;
00238         xc=(source->w<<15) - ((target->w>>1)*(cosfp+sinfp));
00239         yc=(source->h<<15) - ((target->h>>1)*(cosfp-sinfp));
00240 
00241         sgeLock(target);
00242         for ( y=0; y<target->h; y++ ) {
00243 
00244                 tx=xc;
00245                 ty=yc;
00246 
00247                 for( x=0; x<target->w; x++ ) {
00248 
00249 
00250                         tempx=(tx>>16);
00251                         tempy=(ty>>16);
00252 
00253                         if( (tempx>=0) && (tempx<source->w) && (tempy>=0) && (tempy<source->h) ) {
00254                                 if (x>maxx) {
00255                                         maxx=x;
00256                                 }
00257                                 if (y>maxy) {
00258                                         maxy=y;
00259                                 }
00260                                 if (x<minx) {
00261                                         minx=x;
00262                                 }
00263                                 if (y<miny) {
00264                                         miny=y;
00265                                 }
00266                                 switch (source->format->BitsPerPixel) {
00267                                         case 8:
00268                                                 *(dst8+x+y*targetpitch) = *(src8+tempx+tempy*sourcepitch);
00269                                                 break;
00270                                         case 16:
00271                                                 *(dst16+x+y*targetpitch) = *(src16+tempx+tempy*sourcepitch);
00272                                                 break;
00273                                         default:
00274                                                 *(dst32+x+y*targetpitch) = *(src32+tempx+tempy*sourcepitch);
00275                                                 break;
00276                                 }
00277                         }
00278 
00279                         tx+=cosfp;
00280                         ty-=sinfp;
00281                 }
00282                 xc+=sinfp;
00283                 yc+=cosfp;
00284         }
00285         sgeUnlock(target);
00286 
00287         r.x=minx;
00288         r.y=miny;
00289         r.w=maxx-minx;
00290         r.h=maxy-miny;
00291 
00292         ret=SDL_CreateRGBSurface(
00293                         source->flags,
00294                         r.w,
00295                         r.h,
00296                         source->format->BitsPerPixel,
00297                         source->format->Rmask,
00298                         source->format->Gmask,
00299                         source->format->Bmask,
00300                         source->format->Amask
00301         );
00302 
00303         SDL_SetAlpha(target, 0, 0);
00304 
00305         SDL_BlitSurface(target, &r, ret, NULL);
00306         SDL_FreeSurface(target);
00307 
00308         return ret;
00309 }
00310 
00311 SDL_Surface *sgeChangeSDLSurfaceAlpha(SDL_Surface *s, Uint8 alpha) {
00312         int x,y;
00313         SDL_Surface *ret=sgeDuplicateSDLSurface(s);
00314         SGEPIXELINFO *pi;
00315 
00316         sgeLock(ret);
00317         for (y=0;y<ret->h;y++) {
00318                 for (x=0;x<ret->w;x++) {
00319                         pi=sgeGetPixel(ret,x,y);
00320                         pi->a=pi->a*alpha/256;
00321                         sgeDrawPixel(ret,x,y,sgeMakeColor(ret,pi->r,pi->g,pi->b,pi->a));
00322                         sgePixelInfoDestroy(pi);
00323                 }
00324         }
00325         sgeUnlock(ret);
00326         return ret;
00327 }
00328 
00329 SDL_Surface *sgeCreateSDLSurface(int width, int height, int depth, Uint32 sdlflags) {
00330         SDL_Surface *ret;
00331         Uint32 rmask,gmask,bmask,amask;
00332 
00333 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
00334         rmask = 0xff000000;
00335         gmask = 0x00ff0000;
00336         bmask = 0x0000ff00;
00337         amask = 0x000000ff;
00338 #else
00339         rmask = 0x000000ff;
00340         gmask = 0x0000ff00;
00341         bmask = 0x00ff0000;
00342         amask = 0xff000000;
00343 #endif
00344 
00345         if (sdlflags==0) {
00346                 sdlflags=SDL_SWSURFACE;
00347         }
00348 
00349         ret=SDL_CreateRGBSurface(sdlflags, width, height, depth, rmask, gmask, bmask, amask);
00350         if (ret==NULL) {
00351                 sgeBailOut("cannot create new surface: %s\n", SDL_GetError ());
00352         }
00353         return ret;
00354 }
00355 
00356 SDL_Surface *sgeCreateVideoSurface(int width, int height, int depth, Uint32 sdlflags) {
00357         SDL_Surface *s=sgeCreateSDLSurface(width, height, depth, sdlflags);
00358         SDL_Surface *ret;
00359 
00360         ret=SDL_DisplayFormatAlpha(s);
00361         if (ret!=NULL) {
00362                 SDL_FreeSurface(s);
00363                 return ret;
00364         }
00365 
00366         return s;
00367 }
00368 
00369 SDL_Surface *sgeConvertToGrey(SDL_Surface *src) {
00370         SGEPIXELINFO *info;
00371         SDL_Surface *ret=sgeDuplicateSDLSurface(src);
00372         int x,y;
00373         int grey;
00374 
00375         sgeLock(ret);
00376         for (y=0;y<src->h;y++) {
00377                 for (x=0;x<src->w;x++) {
00378                         info=sgeGetPixel(src, x, y);
00379                         grey=(int)(0.3*(float)info->r+0.59*(float)info->g+0.11*(float)info->b);
00380                         sgeDrawPixel(ret, x, y, sgeMakeColor(ret, grey, grey, grey, info->a));
00381                         sgeFree(info);
00382                 }
00383         }
00384         sgeUnlock(ret);
00385         return ret;
00386 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines