Main Page | Namespace List | Class Hierarchy | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

SDLMain.cpp

Go to the documentation of this file.
00001 /**
00002     This class is responsible for setting up a screen,
00003     providing access to the screen and handling screen updates.
00004 
00005     This class is a singleton and one can only access it thru:
00006         SDLMain *SDLMain::getInstance()
00007 
00008     Upon the first call of this method the SDL Screen is initialized.
00009     (Later from a config - file - no hardcoded parameters)
00010 
00011     Using the methods:
00012         void SDLMain::shutdown()
00013         void SDLMain::shutdown(std::string message, unsigned int errorNo)
00014     
00015     The client can shutdown SDL usage, either with or without an error message.
00016     (exit() is called - so the program quits!)
00017 
00018     With the methods:
00019 
00020         void SDLMain::addUpdateRect(const SDL_Rect &saveRegion)
00021         void SDLMain::addUpdateRect(signed short x, signed short y, unsigned short w, unsigned short h)
00022     
00023     The Client can add update regions of the screen for the next update "round".
00024     At the moment only 
00025           const int NUM_UPDATE_RECTS = 500;
00026     update-rectangles are supported. But changing the value for higher needs is ok.
00027 
00028     Using:
00029         void SDLMain::updateScreen()
00030     Updates the screen, the update methods respects last set update regions, and
00031     page flipping for double buffering!
00032 
00033     The methods:
00034         int SDLMain::getPageNo()
00035         int SDLMain::getCurrentPage()
00036     Are provided for double-buffering, they 
00037     a. return the number of pages currently used (right now either 1 or 2)
00038     b. the current page number (0 or 1)
00039   */
00040 
00041 #ifdef WIN32
00042 #pragma warning(disable : 4786 )
00043 #endif
00044 #include "SDLMain.h"
00045 #include "SDL_rotozoom.h"
00046 
00047 #include <stdlib.h>
00048 #include <stdio.h> 
00049 #include <stdarg.h>
00050 
00051 SDLMain *SDLMain::mInstance = 0;
00052 SDL_Surface *SDLMain::mScreen = 0;
00053 SDL_Rect *SDLMain::mRects = 0;
00054 
00055 int SDLMain::mCurrentCount = 0;
00056 int SDLMain::mNoPages = 1;      // default
00057 int SDLMain::mPage = 0;
00058 
00059 int SDLMain::mWidth = 640;
00060 int SDLMain::mHeight = 480;
00061 int SDLMain::mDepth = 32;
00062 bool SDLMain::mUpdateWholeScreen = false;
00063     
00064 bool SDLMain::mIsHardware = true;
00065 bool SDLMain::mIsDoublebuffer = true;
00066 bool SDLMain::mIsAnyFormat = true;
00067 bool SDLMain::mIsFullscreen = false;
00068 unsigned int SDLMain::mMode = 0;
00069 
00070 unsigned int SDLMain::mAudioFormat = AUDIO_S16;
00071 unsigned int SDLMain::mAudioChannels = 2;
00072 unsigned int SDLMain::mAudioBuffers = 4096;
00073 unsigned int SDLMain::mAudioRate = 44100;
00074 bool SDLMain::mSDLInit = false;
00075 const char *SDLMain::CLASS = "SDLMain";
00076 
00077 SDLMain::SDLMain() // private
00078 {
00079     static char *functionName="SDLMain";
00080     LOG_ENTER 
00081     MESSAGE_SCREEN_CHANGED.setSubtype(SCREEN_CHANGED_MESSAGE);
00082 
00083     LOG_INFO_MESSAGE("Initializing SDL.") 
00084 
00085     /* Initialize the SDL library */
00086     if( SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0 ) 
00087     {
00088         shutdown((std::string) "Couldn't initialize SDL: " + SDL_GetError(), 1);
00089     }
00090     LOG_INFO_MESSAGE("SDL initialized.") 
00091 
00092     if (Mix_OpenAudio(mAudioRate, mAudioFormat, mAudioChannels, mAudioBuffers))
00093     {
00094         shutdown((std::string) "Couldn't initialize SDL_Mixer: " + SDL_GetError(), 1);
00095     }
00096     LOG_INFO_MESSAGE("SDL_Mixer initialized.") 
00097     SDL_EnableUNICODE(1);
00098 
00099 
00100     resetVideo();
00101     
00102     // build number of update recangles!
00103     mRects = new SDL_Rect[NUM_UPDATE_RECTS];
00104     mCurrentCount = 0;
00105     mSDLInit = true;
00106     LOG_EXIT
00107 }
00108 
00109 SDLMain::~SDLMain()
00110 {
00111     static char *functionName="~SDLMain";
00112     LOG_ENTER 
00113     SDLMain *instance = mInstance;
00114     mInstance = 0;
00115     if (instance != 0)
00116     {
00117         delete instance;
00118         instance = 0;
00119     }
00120     if (mRects != 0)
00121     {
00122         delete []mRects;
00123         mRects = 0;
00124     }
00125     LOG_EXIT
00126 }
00127 
00128 void SDLMain::clearScreen( int red, int green, int blue )
00129 {
00130     long int color = SDL_MapRGB( mScreen->format, red, green, blue );
00131     SDL_FillRect( mScreen, 0, color ); 
00132     SDL_UpdateRect( mScreen, 0, 0, 0, 0 );
00133 }
00134 
00135 SDLMain *SDLMain::getInstance()
00136 {
00137     static char *functionName="getInstance";
00138     LOG_ENTER 
00139     if (mInstance == 0)
00140     {
00141         mInstance = new SDLMain();
00142     }
00143     LOG_EXIT
00144     return mInstance;
00145 }
00146 
00147 void SDLMain::shutdown()
00148 {
00149     shutdown("Quiting SDL.\n", 0);
00150 }
00151 
00152 void SDLMain::shutdown(std::string message, unsigned int errorNo)
00153 {
00154     static char *functionName="shutdown";
00155     LOG_ENTER 
00156     SDLMain *instance = mInstance;
00157     mInstance = 0;
00158     if (instance != 0)
00159     {
00160         delete instance;
00161     }
00162 
00163     /* Shutdown all subsystems */
00164     Mix_CloseAudio();
00165     SDL_Quit();
00166     mSDLInit = false;
00167     LOG_ERROR_PRINT(message, (long)errorNo) 
00168 
00169     LOG_EXIT
00170     exit(errorNo);
00171 }
00172 
00173 void SDLMain::adjustClipping(SDL_Rect &newRect, SDL_Rect &oldRect)
00174 {
00175     if (newRect.x<oldRect.x)
00176     {
00177         newRect.w -= oldRect.x-newRect.x;
00178         newRect.x = oldRect.x;
00179     }
00180     if (newRect.w > 60000)
00181     {
00182         newRect.w = 0;
00183     }
00184     if (newRect.y<oldRect.y)
00185     {
00186         newRect.h -= oldRect.y-newRect.y;
00187         newRect.y = oldRect.y;
00188     }
00189     if (newRect.h > 60000)
00190     {
00191         newRect.h = 0;
00192     }
00193     if (newRect.x + newRect.w > oldRect.x + oldRect.w)
00194     {
00195         newRect.w -= (newRect.x + newRect.w) - (oldRect.x + oldRect.w); 
00196     }
00197     if (newRect.y + newRect.h > oldRect.y + oldRect.h)
00198     {
00199         newRect.h -= (newRect.y + newRect.h) - (oldRect.y + oldRect.h); 
00200     }
00201 
00202     if (newRect.x < 0) 
00203     {
00204         newRect.w += newRect.x;
00205         newRect.x = 0;
00206     }
00207     if (newRect.y < 0) 
00208     {
00209         newRect.h += newRect.y;
00210         newRect.y = 0;
00211     }
00212     if (newRect.w > 60000) 
00213         newRect.w = 0;
00214     if (newRect.h > 60000) 
00215         newRect.h = 0;
00216 }
00217 
00218 void SDLMain::setScreenWidth(int w)
00219 {
00220     static char *functionName="setScreenWidth";
00221     LOG_ENTER 
00222     if (mWidth == w)
00223     {
00224         LOG_EXIT
00225         return;
00226     }
00227     mWidth = w;
00228     resetVideo();
00229     LOG_EXIT
00230 }
00231 
00232 void SDLMain::setScreenHeight(int h)
00233 {
00234     static char *functionName="setScreenHeight";
00235     LOG_ENTER 
00236     if (mHeight == h)
00237     {
00238         LOG_EXIT
00239         return;
00240     }
00241     mHeight = h;
00242     resetVideo();
00243     LOG_EXIT
00244 }
00245 
00246 void SDLMain::setScreenDepth(int d)
00247 {
00248     static char *functionName="setScreenDepth";
00249     LOG_ENTER 
00250     if (mDepth == d)
00251     {
00252         LOG_EXIT
00253         return;
00254     }
00255     mDepth = d;
00256     resetVideo();
00257     LOG_EXIT
00258 }
00259 
00260 void SDLMain::setHardwareSurface(bool h)
00261 {
00262     static char *functionName="setHardwareSurface";
00263     LOG_ENTER 
00264     if (mIsHardware == h)
00265     {
00266         LOG_EXIT
00267         return;
00268     }
00269     mIsHardware = h;
00270     resetVideo();
00271     LOG_EXIT
00272 }
00273 
00274 void SDLMain::setDoubleBufferSurface(bool d)
00275 {
00276     static char *functionName="setDoubleBufferSurface";
00277     LOG_ENTER 
00278     if (mIsDoublebuffer == d)
00279     {
00280         LOG_EXIT
00281         return;
00282     }
00283     mIsDoublebuffer = d;
00284     resetVideo();
00285     LOG_EXIT
00286 }
00287 
00288 void SDLMain::setFullscreenSurface(bool f)
00289 {
00290     static char *functionName="setFullscreenSurface";
00291     LOG_ENTER 
00292     if (mIsFullscreen == f)
00293     {
00294         LOG_EXIT
00295         return;
00296     }
00297     mIsFullscreen = f;
00298     resetVideo();
00299     LOG_EXIT
00300 }
00301 
00302 void SDLMain::setUseScreenAnyhowSurface(bool a)
00303 {
00304     static char *functionName="setUseScreenAnyhowSurface";
00305     LOG_ENTER 
00306     if (mIsAnyFormat == a)
00307     {
00308         LOG_EXIT
00309         return;
00310     }
00311     mIsAnyFormat = a;
00312     resetVideo();
00313     LOG_EXIT
00314 }
00315 
00316 unsigned int SDLMain::getMode()
00317 {
00318     static char *functionName="getMode";
00319     LOG_ENTER 
00320     unsigned int mode = 0;
00321     if (isHardwareSurface())
00322     {
00323         mode = mode | SDL_HWSURFACE;
00324     }
00325     else 
00326     {
00327         mode = mode | SDL_SWSURFACE;
00328     }
00329 
00330     if (isDoubleBufferSurface())
00331     {
00332         mode = mode | SDL_DOUBLEBUF;
00333     }
00334 
00335     if (isFullscreenSurface())
00336     {
00337         mode = mode | SDL_FULLSCREEN;
00338     }
00339 
00340     if (isUseScreenAnyhowSurface())
00341     {
00342         mode = mode | SDL_ANYFORMAT;
00343     }
00344     mMode = mode;   
00345     LOG_EXIT
00346     return mMode;
00347 }
00348 
00349 void SDLMain::resetVideo(void)
00350 {
00351     static char *functionName="resetVideo";
00352     LOG_ENTER 
00353     // should be read from an ini file at some stage
00354     mScreen = SDL_SetVideoMode( getScreenWidth(), 
00355                                 getScreenHeight(), 
00356                                 getScreenDepth(), 
00357                                 getMode());
00358 
00359     if ( mScreen == NULL ) 
00360     {
00361         std::string message;
00362         message = message + "Couldn't set video mode: " + SDL_GetError();
00363         shutdown(message, 1);
00364     }
00365     LOG_INFO_PRINT("Set Mode at bits-per-pixel mode:", (long)mScreen->format->BitsPerPixel) 
00366     if (mScreen->flags & SDL_DOUBLEBUF) 
00367     {
00368         mNoPages = 2;
00369         mPage = 0;
00370     }
00371 //  mIsDoublebuffer = (mScreen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF;
00372 //  mIsHardware = (mScreen->flags & SDL_HWSURFACE) == SDL_HWSURFACE;
00373 //  mIsFullscreen = (mScreen->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN;
00374 
00375     if (mIsHardware) 
00376     {
00377         LOG_INFO_MESSAGE("SDL_HWSURFACE") 
00378     }
00379     if (mIsDoublebuffer) 
00380     {
00381         LOG_INFO_MESSAGE("DOUBLEBUFFER") 
00382     }
00383     if (mIsFullscreen) 
00384     {
00385         LOG_INFO_MESSAGE("FULLSCREEN") 
00386     }
00387 
00388     if (mInstance != 0)
00389     {
00390         mInstance->sendMessage(mInstance->MESSAGE_SCREEN_CHANGED);
00391     }
00392     SDL_ShowCursor(SDL_DISABLE);
00393     LOG_EXIT
00394 }
00395 
00396 void SDLMain::toggleFullscreen()
00397 {
00398     static char *functionName="toggleFullscreen";
00399     LOG_ENTER 
00400     setFullscreenSurface(!isFullscreenSurface());
00401     LOG_EXIT
00402 }
00403 
00404 void SDLMain::addUpdateRect(const SDL_Rect &saveRegion)
00405 {
00406     static char *functionName="addUpdateRect";
00407     if (mUpdateWholeScreen)
00408     {
00409         return;
00410     }
00411 
00412     if (mRects == 0)
00413     {
00414         return;
00415     }
00416     if (mCurrentCount >= NUM_UPDATE_RECTS)
00417     {
00418         SDLMain::shutdown((std::string)"Not enough Update Rects available: " + SDL_GetError(), 1);
00419     }
00420     mRects[mCurrentCount].x = saveRegion.x;
00421     mRects[mCurrentCount].y = saveRegion.y;
00422     mRects[mCurrentCount].w = saveRegion.w;
00423     mRects[mCurrentCount].h = saveRegion.h;
00424     mCurrentCount++;
00425 }
00426 
00427 void SDLMain::addUpdateRect(signed short x, signed short y, unsigned short w, unsigned short h)
00428 {
00429     static char *functionName="addUpdateRect";
00430     if (mUpdateWholeScreen)
00431     {
00432         return;
00433     }
00434     if (mRects == 0)
00435     {
00436         return;
00437     }
00438     if (mCurrentCount >= NUM_UPDATE_RECTS)
00439     {
00440         SDLMain::shutdown((std::string)"Not enough Update Rects available: " + SDL_GetError(), 1);
00441     }
00442     mRects[mCurrentCount].x = x;
00443     mRects[mCurrentCount].y = y;
00444     mRects[mCurrentCount].w = w;
00445     mRects[mCurrentCount].h = h;
00446     mCurrentCount++;
00447 }
00448 
00449 void SDLMain::updateScreen()
00450 {
00451     static char *functionName="updateScreen";
00452     if (mScreen->flags & SDL_DOUBLEBUF)
00453     {
00454         SDL_Flip(mScreen);
00455         mPage = (mPage + 1) % mNoPages;
00456     }
00457     else
00458     {
00459         if (mUpdateWholeScreen)
00460         {
00461             SDL_UpdateRect(mScreen, 0,0,0,0);
00462         }
00463         else
00464         {
00465             if (mRects == 0)
00466             {
00467                 return;
00468             }
00469             SDL_UpdateRects(mScreen, mCurrentCount, mRects);
00470         }
00471     }
00472 
00473     mCurrentCount = 0;
00474 }
00475 
00476 int SDLMain::getPageNo()
00477 {
00478     return mNoPages;
00479 }
00480 
00481 int SDLMain::getCurrentPage()
00482 {
00483     return mPage;
00484 }
00485 
00486 Uint32 SDLMain::getPixel(SDL_Surface *Surface, Sint32 X, Sint32 Y)
00487 {
00488     static char *functionName="getPixel";
00489     Uint32 Bpp;
00490 
00491     if ((X<0) || (X>=Surface->w))
00492     {
00493         return (Uint32)-1;
00494     }
00495    
00496     Bpp = Surface->format->BytesPerPixel;
00497 
00498     // Get the pixel
00499     switch(Bpp) 
00500     {
00501         case 1:
00502             return *((Uint8 *)Surface->pixels + Y * Surface->pitch + X);
00503             break;
00504         case 2:
00505             return *((Uint16 *)Surface->pixels + Y * Surface->pitch/2 + X);
00506             break;
00507         case 3: 
00508         { // Format/endian independent 
00509             Uint8 r, g, b;
00510             Uint8  *bits;
00511             bits = ((Uint8 *)Surface->pixels)+Y*Surface->pitch+X*Bpp;
00512          
00513             r = *((bits)+Surface->format->Rshift/8);
00514             g = *((bits)+Surface->format->Gshift/8);
00515             b = *((bits)+Surface->format->Bshift/8);
00516          
00517             return SDL_MapRGB(Surface->format, r, g, b);
00518         }
00519         break;
00520         case 4:
00521             return *((Uint32 *)Surface->pixels + Y * Surface->pitch/4 + X);
00522             break;
00523     }
00524     return -1;
00525 }
00526 
00527 void SDLMain::setPixel(SDL_Surface *surface, Sint32 x, Sint32 y, Uint32 color)
00528 {
00529     static char *functionName="setPixel";
00530     static Uint8 ri, gi, bi;
00531     static Uint8 *bits;
00532     static Uint8 bpp;
00533     static SDL_Rect rect;
00534 
00535     bpp = surface->format->BytesPerPixel;
00536     bits = ((Uint8 *) surface->pixels) + y * surface->pitch + x * bpp;
00537     /* Set the pixel */
00538     switch (bpp) {
00539         case 1:
00540             *((Uint8 *) (bits)) = (Uint8) color;
00541             break;
00542 
00543         case 2:
00544             *((Uint16 *) (bits)) = (Uint16) color;
00545             break;
00546 
00547         case 3: {           /* Format/endian independent */
00548 
00549                 ri = (color >> surface->format->Rshift) & 0xFF;
00550                 gi = (color >> surface->format->Gshift) & 0xFF;
00551                 bi = (color >> surface->format->Bshift) & 0xFF;
00552                 *((bits) + surface->format->Rshift / 8) = ri;
00553                 *((bits) + surface->format->Gshift / 8) = gi;
00554                 *((bits) + surface->format->Bshift / 8) = bi;
00555             }
00556             break;
00557 
00558         case 4:
00559             *((Uint32 *) (bits)) = (Uint32) color;
00560             break;
00561     }
00562 }
00563 
00564 SDL_Surface *SDLMain::scale(SDL_Surface *surface, int width, int height)
00565 {
00566     static char *functionName="scale";
00567     LOG_ENTER 
00568     double zoomx;
00569     double zoomy;
00570     zoomx = (double)(((double)(width)) / ((double) surface->w));
00571     zoomy = (double)(((double)(height)) / ((double) surface->h));
00572     SDL_Surface *ret = zoomSurface(surface, zoomx, zoomy, 0);
00573     LOG_EXIT
00574     return ret;
00575 }
00576 
00577 SDL_Surface *SDLMain::scale(SDL_Surface *surface, int width, int divideX, int height, int divideY)
00578 {
00579     static char *functionName="scale";
00580     LOG_ENTER 
00581     double zoomx;
00582     double zoomy;
00583     zoomx = (double)(((double)(width)) / ((double) divideX));
00584     zoomy = (double)(((double)(height)) / ((double) divideY));
00585     SDL_Surface *ret = zoomSurface(surface, zoomx, zoomy, 0);
00586     LOG_EXIT
00587     return ret;
00588 }
00589 
00590 SDL_Surface *SDLMain::scale(SDL_Surface *surface, double factor)
00591 {
00592     return zoomSurface(surface, factor, factor, 0);
00593 }
00594 
00595 int SDLMain::scaleX(int width, int divideX, int x)
00596 {
00597     static char *functionName="scaleX";
00598     LOG_ENTER 
00599     double zoomx;
00600     zoomx = (double)(((double)(width)) / ((double) divideX));
00601     int destx, desty;
00602     
00603     zoomSurfaceSize(x, 1, zoomx, 1, &destx, &desty);
00604     if (x==0) destx = 0;
00605     LOG_EXIT
00606     return destx;
00607 }
00608 
00609 int SDLMain::scaleY(int height, int divideY, int y)
00610 {
00611     static char *functionName="scaleY";
00612     LOG_ENTER 
00613     double zoomy;
00614     zoomy = (double)(((double)(height)) / ((double) divideY));
00615     int destx, desty;
00616     zoomSurfaceSize(1, y, 1, zoomy, &destx, &desty);
00617     if (y==0) desty = 0;
00618     LOG_EXIT
00619     return desty;
00620 }
00621 
00622 
00623 /* Clipping based heavily on code from                       */
00624 /* http://www.ncsa.uiuc.edu/Vis/Graphics/src/clipCohSuth.c   */
00625 #define CLIP_LEFT_EDGE   0x1
00626 #define CLIP_RIGHT_EDGE  0x2
00627 #define CLIP_BOTTOM_EDGE 0x4
00628 #define CLIP_TOP_EDGE    0x8
00629 #define CLIP_INSIDE(a)   (!a)
00630 #define CLIP_REJECT(a,b) (a&b)
00631 #define CLIP_ACCEPT(a,b) (!(a|b))
00632 
00633 static int clipEncode(Sint16 x, Sint16 y, Sint16 left, Sint16 top, Sint16 right, Sint16 bottom)
00634 {
00635     char *CLASS = "None";
00636     static char *functionName="clipEncode";
00637     LOG_ENTER 
00638     int code = 0;
00639     if (x < left) {
00640     code |= CLIP_LEFT_EDGE;
00641     } else if (x > right) {
00642     code |= CLIP_RIGHT_EDGE;
00643     }
00644     if (y < top) {
00645     code |= CLIP_TOP_EDGE;
00646     } else if (y > bottom) {
00647     code |= CLIP_BOTTOM_EDGE;
00648     }
00649     LOG_EXIT
00650     return code;
00651 }
00652 
00653 static int clipLine(SDL_Surface * dst, Sint16 * x1, Sint16 * y1, Sint16 * x2, Sint16 * y2)
00654 {
00655     char *CLASS = "None";
00656     static char *functionName="clipLine";
00657     LOG_ENTER 
00658     Sint16 left, right, top, bottom;
00659     int code1, code2;
00660     int draw = 0;
00661     Sint16 swaptmp;
00662     float m;
00663 
00664     /*
00665      * Get clipping boundary 
00666      */
00667     left = dst->clip_rect.x;
00668     right = dst->clip_rect.x + dst->clip_rect.w - 1;
00669     top = dst->clip_rect.y;
00670     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
00671 
00672     while (1) {
00673     code1 = clipEncode(*x1, *y1, left, top, right, bottom);
00674     code2 = clipEncode(*x2, *y2, left, top, right, bottom);
00675     if (CLIP_ACCEPT(code1, code2)) {
00676         draw = 1;
00677         break;
00678     } else if (CLIP_REJECT(code1, code2))
00679         break;
00680     else {
00681         if (CLIP_INSIDE(code1)) {
00682         swaptmp = *x2;
00683         *x2 = *x1;
00684         *x1 = swaptmp;
00685         swaptmp = *y2;
00686         *y2 = *y1;
00687         *y1 = swaptmp;
00688         swaptmp = code2;
00689         code2 = code1;
00690         code1 = swaptmp;
00691         }
00692         if (*x2 != *x1) {
00693         m = (*y2 - *y1) / (float) (*x2 - *x1);
00694         } else {
00695         m = 1.0f;
00696         }
00697         if (code1 & CLIP_LEFT_EDGE) {
00698         *y1 += (Sint16) ((left - *x1) * m);
00699         *x1 = left;
00700         } else if (code1 & CLIP_RIGHT_EDGE) {
00701         *y1 += (Sint16) ((right - *x1) * m);
00702         *x1 = right;
00703         } else if (code1 & CLIP_BOTTOM_EDGE) {
00704         if (*x2 != *x1) {
00705             *x1 += (Sint16) ((bottom - *y1) / m);
00706         }
00707         *y1 = bottom;
00708         } else if (code1 & CLIP_TOP_EDGE) {
00709         if (*x2 != *x1) {
00710             *x1 += (Sint16) ((top - *y1) / m);
00711         }
00712         *y1 = top;
00713         }
00714     }
00715     }
00716 
00717     LOG_EXIT
00718     return draw;
00719 }
00720 
00721 
00722 #define clip_xmin(surface) surface->clip_rect.x
00723 #define clip_xmax(surface) surface->clip_rect.x+surface->clip_rect.w-1
00724 #define clip_ymin(surface) surface->clip_rect.y
00725 #define clip_ymax(surface) surface->clip_rect.y+surface->clip_rect.h-1
00726 
00727 int _putPixelAlpha(SDL_Surface * surface, Sint16 x, Sint16 y, Uint32 color, Uint8 alpha)
00728 {
00729     char *CLASS = "None";
00730     static char *functionName="_putPixelAlpha";
00731     LOG_ENTER 
00732 
00733     Uint32 Rmask = surface->format->Rmask, Gmask =
00734     surface->format->Gmask, Bmask = surface->format->Bmask, Amask = surface->format->Amask;
00735     Uint32 R, G, B, A = 0;
00736 
00737     if (x >= clip_xmin(surface) && x <= clip_xmax(surface)
00738     && y >= clip_ymin(surface) && y <= clip_ymax(surface)) {
00739 
00740     switch (surface->format->BytesPerPixel) {
00741     case 1:{        /* Assuming 8-bpp */
00742         if (alpha == 255) {
00743             *((Uint8 *) surface->pixels + y * surface->pitch + x) = color;
00744         } else {
00745             Uint8 *pixel = (Uint8 *) surface->pixels + y * surface->pitch + x;
00746 
00747             Uint8 dR = surface->format->palette->colors[*pixel].r;
00748             Uint8 dG = surface->format->palette->colors[*pixel].g;
00749             Uint8 dB = surface->format->palette->colors[*pixel].b;
00750             Uint8 sR = surface->format->palette->colors[color].r;
00751             Uint8 sG = surface->format->palette->colors[color].g;
00752             Uint8 sB = surface->format->palette->colors[color].b;
00753 
00754             dR = dR + ((sR - dR) * alpha >> 8);
00755             dG = dG + ((sG - dG) * alpha >> 8);
00756             dB = dB + ((sB - dB) * alpha >> 8);
00757 
00758             *pixel = SDL_MapRGB(surface->format, dR, dG, dB);
00759         }
00760         }
00761         break;
00762 
00763     case 2:{        /* Probably 15-bpp or 16-bpp */
00764         if (alpha == 255) {
00765             *((Uint16 *) surface->pixels + y * surface->pitch / 2 + x) = color;
00766         } else {
00767             Uint16 *pixel = (Uint16 *) surface->pixels + y * surface->pitch / 2 + x;
00768             Uint32 dc = *pixel;
00769 
00770             R = ((dc & Rmask) + (((color & Rmask) - (dc & Rmask)) * alpha >> 8)) & Rmask;
00771             G = ((dc & Gmask) + (((color & Gmask) - (dc & Gmask)) * alpha >> 8)) & Gmask;
00772             B = ((dc & Bmask) + (((color & Bmask) - (dc & Bmask)) * alpha >> 8)) & Bmask;
00773             if (Amask)
00774             A = ((dc & Amask) + (((color & Amask) - (dc & Amask)) * alpha >> 8)) & Amask;
00775 
00776             *pixel = R | G | B | A;
00777         }
00778         }
00779         break;
00780 
00781     case 3:{        /* Slow 24-bpp mode, usually not used */
00782         Uint8 *pix = (Uint8 *) surface->pixels + y * surface->pitch + x * 3;
00783         Uint8 rshift8 = surface->format->Rshift / 8;
00784         Uint8 gshift8 = surface->format->Gshift / 8;
00785         Uint8 bshift8 = surface->format->Bshift / 8;
00786         Uint8 ashift8 = surface->format->Ashift / 8;
00787 
00788 
00789         if (alpha == 255) {
00790             *(pix + rshift8) = color >> surface->format->Rshift;
00791             *(pix + gshift8) = color >> surface->format->Gshift;
00792             *(pix + bshift8) = color >> surface->format->Bshift;
00793             *(pix + ashift8) = color >> surface->format->Ashift;
00794         } else {
00795             Uint8 dR, dG, dB, dA = 0;
00796             Uint8 sR, sG, sB, sA = 0;
00797 
00798             pix = (Uint8 *) surface->pixels + y * surface->pitch + x * 3;
00799 
00800             dR = *((pix) + rshift8);
00801             dG = *((pix) + gshift8);
00802             dB = *((pix) + bshift8);
00803             dA = *((pix) + ashift8);
00804 
00805             sR = (color >> surface->format->Rshift) & 0xff;
00806             sG = (color >> surface->format->Gshift) & 0xff;
00807             sB = (color >> surface->format->Bshift) & 0xff;
00808             sA = (color >> surface->format->Ashift) & 0xff;
00809 
00810             dR = dR + ((sR - dR) * alpha >> 8);
00811             dG = dG + ((sG - dG) * alpha >> 8);
00812             dB = dB + ((sB - dB) * alpha >> 8);
00813             dA = dA + ((sA - dA) * alpha >> 8);
00814 
00815             *((pix) + rshift8) = dR;
00816             *((pix) + gshift8) = dG;
00817             *((pix) + bshift8) = dB;
00818             *((pix) + ashift8) = dA;
00819         }
00820         }
00821         break;
00822 
00823     case 4:{        /* Probably 32-bpp */
00824         if (alpha == 255) {
00825             *((Uint32 *) surface->pixels + y * surface->pitch / 4 + x) = color;
00826         } else {
00827             Uint32 *pixel = (Uint32 *) surface->pixels + y * surface->pitch / 4 + x;
00828             Uint32 dc = *pixel;
00829 
00830             R = ((dc & Rmask) + (((color & Rmask) - (dc & Rmask)) * alpha >> 8)) & Rmask;
00831             G = ((dc & Gmask) + (((color & Gmask) - (dc & Gmask)) * alpha >> 8)) & Gmask;
00832             B = ((dc & Bmask) + (((color & Bmask) - (dc & Bmask)) * alpha >> 8)) & Bmask;
00833             if (Amask)
00834             A = ((dc & Amask) + (((color & Amask) - (dc & Amask)) * alpha >> 8)) & Amask;
00835 
00836             *pixel = R | G | B | A;
00837         }
00838         }
00839         break;
00840     }
00841     }
00842 
00843     LOG_EXIT
00844     return (0);
00845 }
00846 
00847 /* ----- Pixel - fast, no blending, no locking, clipping */
00848 int pixelColorNolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
00849 {
00850     char *CLASS = "None";
00851     static char *functionName="pixelColorNolock";
00852     LOG_ENTER 
00853     Uint8 alpha;
00854     Uint32 mcolor;
00855     int result = 0;
00856 
00857     /*
00858      * Setup color 
00859      */
00860     alpha = color & 0x000000ff;
00861     mcolor =
00862     SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24,
00863             (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha);
00864 
00865     /*
00866      * Draw 
00867      */
00868     result = _putPixelAlpha(dst, x, y, mcolor, alpha);
00869 
00870     LOG_EXIT
00871     return (result);
00872 }
00873 
00874 
00875 int SDLMain::line(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
00876 {
00877     static char *functionName="line";
00878     LOG_ENTER 
00879     int pixx, pixy;
00880     int x, y;
00881     int dx, dy;
00882     int ax, ay;
00883     int sx, sy;
00884     int swaptmp;
00885     Uint8 *pixel;
00886     Uint8 *colorptr;
00887 
00888     /*
00889      * Clip line and test if we have to draw 
00890      */
00891     if (!(clipLine(dst, &x1, &y1, &x2, &y2))) 
00892     {
00893         LOG_EXIT
00894         return (0);
00895     }
00896 
00897     /*
00898      * Variable setup 
00899      */
00900     dx = x2 - x1;
00901     dy = y2 - y1;
00902     sx = (dx >= 0) ? 1 : -1;
00903     sy = (dy >= 0) ? 1 : -1;
00904 
00905     /* Lock surface */
00906     if (SDL_MUSTLOCK(dst)) 
00907     {
00908         if (SDL_LockSurface(dst) < 0) 
00909         {
00910             LOG_EXIT
00911             return (-1);
00912         }
00913     }
00914 
00915     /*
00916      * Check for alpha blending 
00917      */
00918     if ((color & 255) == 255) 
00919     {
00920 
00921         /*
00922          * No alpha blending - use fast pixel routines 
00923          */
00924 
00925         /*
00926          * Setup color 
00927          */
00928         colorptr = (Uint8 *) & color;
00929         if (SDL_BYTEORDER == SDL_BIG_ENDIAN) 
00930         {
00931             color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
00932         } 
00933         else 
00934         {
00935             color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
00936         }
00937 
00938         /*
00939          * More variable setup 
00940          */
00941         dx = sx * dx + 1;
00942         dy = sy * dy + 1;
00943         pixx = dst->format->BytesPerPixel;
00944         pixy = dst->pitch;
00945         pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y1;
00946         pixx *= sx;
00947         pixy *= sy;
00948         if (dx < dy) 
00949         {
00950             swaptmp = dx;
00951             dx = dy;
00952             dy = swaptmp;
00953             swaptmp = pixx;
00954             pixx = pixy;
00955             pixy = swaptmp;
00956         }
00957 
00958         /*
00959          * Draw 
00960          */
00961         x = 0;
00962         y = 0;
00963         switch (dst->format->BytesPerPixel) 
00964         {
00965             case 1:
00966                 for (; x < dx; x++, pixel += pixx) 
00967                 {
00968                     *pixel = color;
00969                     y += dy;
00970                     if (y >= dx) 
00971                     {
00972                         y -= dx;
00973                         pixel += pixy;
00974                     }
00975                 }
00976                 break;
00977             case 2:
00978                 for (; x < dx; x++, pixel += pixx) 
00979                 {
00980                     *(Uint16 *) pixel = color;
00981                     y += dy;
00982                     if (y >= dx) 
00983                     {
00984                         y -= dx;
00985                         pixel += pixy;
00986                     }
00987                 }
00988                 break;
00989             case 3:
00990                 for (; x < dx; x++, pixel += pixx) 
00991                 {
00992                     if (SDL_BYTEORDER == SDL_BIG_ENDIAN) 
00993                     {
00994                         pixel[0] = (color >> 16) & 0xff;
00995                         pixel[1] = (color >> 8) & 0xff;
00996                         pixel[2] = color & 0xff;
00997                     } 
00998                     else 
00999                     {
01000                         pixel[0] = color & 0xff;
01001                         pixel[1] = (color >> 8) & 0xff;
01002                         pixel[2] = (color >> 16) & 0xff;
01003                     }
01004                     y += dy;
01005                     if (y >= dx) 
01006                     {
01007                         y -= dx;
01008                         pixel += pixy;
01009                     }
01010                 }
01011                 break;
01012             default:        /* case 4 */
01013                 for (; x < dx; x++, pixel += pixx) 
01014                 {
01015                     *(Uint32 *) pixel = color;
01016                     y += dy;
01017                     if (y >= dx) 
01018                     {
01019                         y -= dx;
01020                         pixel += pixy;
01021                     }
01022                 }
01023                 break;
01024             }
01025 
01026         } 
01027         else 
01028         {
01029 
01030         /*
01031          * Alpha blending required - use single-pixel blits 
01032          */
01033         ax = (((dx)<0) ? -(dx) : (dx)) << 1;
01034         ay = (((dy)<0) ? -(dy) : (dy)) << 1;
01035         x = x1;
01036         y = y1;
01037         if (ax > ay) 
01038         {
01039             int d = ay - (ax >> 1);
01040             while (x != x2) 
01041             {
01042                 pixelColorNolock (dst, x, y, color);
01043                 if (d > 0 || (d == 0 && sx == 1)) 
01044                 {
01045                     y += sy;
01046                     d -= ax;
01047                 }
01048                 x += sx;
01049                 d += ay;
01050             }
01051         } 
01052         else 
01053         {
01054             int d = ax - (ay >> 1);
01055 
01056             while (y != y2) 
01057             {
01058                 pixelColorNolock (dst, x, y, color);
01059                 if (d > 0 || ((d == 0) && (sy == 1))) 
01060                 {
01061                     x += sx;
01062                     d -= ay;
01063                 }
01064                 y += sy;
01065                 d += ax;
01066             }
01067         }
01068         pixelColorNolock (dst, x, y, color);
01069 
01070     }
01071 
01072     /* Unlock surface */
01073     if (SDL_MUSTLOCK(dst)) 
01074     {
01075         SDL_UnlockSurface(dst);
01076     }
01077     LOG_EXIT
01078     return (0);
01079 }
01080 
01081 // this function wraps freeing of SDL surfaces
01082 // since data is held in static classes
01083 // some surfaces are tried to be freed after quiting SDL
01084 // especially on hardware surfaces this produces errros
01085 // the hard way is -> don't free 'em if SDL is not initialized anymore!
01086 void  SDLMain::freeSurface(SDL_Surface *surface)
01087 {
01088     if (surface == 0)
01089     {
01090         return;
01091     }
01092     if (!mSDLInit)
01093     {
01094         if (surface->hwdata)
01095         {
01096             return;
01097         }
01098     }
01099     SDL_FreeSurface(surface);
01100 }
01101 
01102 void SDLMain::DrawRoundRect(SDL_Surface * screen, SDL_Rect *rect, Uint32 color, int corner, int thickness)
01103 {
01104     DrawRoundRect(screen, rect->x, rect->y, rect->w, rect->h, color, corner, thickness);
01105 }
01106 
01107 //! Draws a rectangle with rounded corners (based on a routine
01108 //! from SDL_draw library)
01109 void SDLMain::DrawRoundRect(SDL_Surface * screen, int x0, int y0, int w, int h, Uint32 color, int corner, int thickness, bool north, bool south, bool east, bool west)
01110 {
01111     int dx, dy;
01112     int Xcenter, Ycenter, X2center, Y2center;
01113     int d, x = 0;
01114     int diagonalInc, rightInc = 6;
01115 
01116     if (w == 0 || h == 0)
01117     {
01118         return;
01119     }
01120 
01121     if (corner != 0)
01122     {
01123         d = w < h ? w : h;
01124         corner--;
01125         if(corner != 0 && corner + 2 >= d)
01126         {
01127             if(corner + 2 == d)
01128                 corner--;
01129             else
01130                 corner = 0;
01131         }
01132     }
01133 
01134     d = 3 - (corner << 1);
01135     diagonalInc = 10 - (corner << 2);
01136 
01137     // Rectangles
01138     dx = w - (corner << 1);
01139     dy = h - (corner << 1);
01140     Xcenter = x0 + corner;
01141     Ycenter = y0 + corner;
01142 
01143     // Centers
01144     X2center = Xcenter + dx - 1;
01145     Y2center = Ycenter + dy - 1;
01146     SDL_Rect area;
01147 
01148     if (north)
01149     {
01150         area.x=x0+corner;
01151         area.y=y0;
01152         area.w=dx;
01153         area.h=thickness;
01154         if (dx >0)
01155             SDL_FillRect( screen, &area, color); 
01156     }
01157     if (south)
01158     {
01159         area.x=x0+corner;
01160         area.y=y0+h-thickness;
01161         area.w=dx;
01162         area.h=thickness;
01163         if (dx >0)
01164             SDL_FillRect( screen, &area, color); 
01165     }
01166     if (west)
01167     {
01168         area.x=x0;
01169         area.y=y0+corner;
01170         area.w=thickness;
01171         area.h=dy;
01172         if (dy >0)
01173             SDL_FillRect( screen, &area, color); 
01174     }
01175     if (east)
01176     {
01177         area.x=x0+w-thickness;
01178         area.y=y0+corner;
01179         area.w=thickness;
01180         area.h=dy;
01181         if (dy >0)
01182             SDL_FillRect( screen, &area, color); 
01183     }
01184 
01185     
01186     color = color*256+255;
01187     for (int t = 0; t < thickness; t++)
01188     {
01189         while(x <= corner*2)
01190         {
01191             // north
01192             if (north)
01193             {
01194                 line(screen, Xcenter - corner,              Ycenter-x, 
01195                              Xcenter - corner + thickness,  Ycenter-x, color);
01196                 line(screen, Xcenter - x,                   Ycenter-corner, 
01197                              Xcenter - x,                   Ycenter-corner + thickness, color);
01198             }
01199             // west
01200             if (west)
01201             {
01202                 line(screen, Xcenter - corner,              Y2center + x, 
01203                              Xcenter - corner + thickness,  Y2center + x, color);
01204                 line(screen, Xcenter - x,                   Y2center+corner - thickness, 
01205                              Xcenter - x,                   Y2center+corner, color);
01206             }
01207 
01208             // east
01209             if (east)
01210             {
01211                 line(screen, X2center + corner - thickness, Ycenter - x, 
01212                              X2center + corner,             Ycenter - x, color);
01213                 line(screen, X2center + x,                  Ycenter - corner, 
01214                              X2center + x,                  Ycenter - corner + thickness, color);
01215             }
01216 
01217             // south
01218             if (south)
01219             {
01220                 line(screen, X2center + x,                  Y2center + corner - thickness, 
01221                              X2center + x,                  Y2center + corner, color);
01222                 line(screen, X2center + corner - thickness, Y2center + x, 
01223                              X2center + corner,             Y2center + x, color);
01224             }
01225             if(d >= 0)
01226             {
01227                 d += diagonalInc;
01228                 diagonalInc += 8;
01229                 corner--;
01230             }
01231             else
01232             {
01233                 d += rightInc;
01234                 diagonalInc += 4;
01235             }
01236             rightInc += 4;
01237             x++;
01238         }
01239     }
01240 }
01241 
01242 // Draws a rectangle with rounded corners (based on a routine
01243 // from SDL_draw library)
01244 void SDLMain::DrawRoundRectFill(SDL_Surface * screen, int x0, int y0, int w, int h, Uint32 color, int corner)
01245 {
01246     int dx, dy;
01247     int Xcenter, Ycenter, X2center, Y2center;
01248     int d, x = 0;
01249     int diagonalInc, rightInc = 6;
01250 
01251     if(w == 0 || h == 0)
01252         return;
01253 
01254     if(corner != 0)
01255     {
01256         d = w < h ? w : h;
01257         corner--;
01258         if(corner != 0 && corner + 2 >= d)
01259         {
01260             if(corner + 2 == d)
01261                 corner--;
01262             else
01263                 corner = 0;
01264         }
01265     }
01266 
01267     d = 3 - (corner << 1);
01268     diagonalInc = 10 - (corner << 2);
01269 
01270     // Rectangles
01271     dx = w - (corner << 1);
01272     Xcenter = x0 + corner;
01273     dy = h - (corner << 1);
01274     Ycenter = y0 + corner;
01275 
01276     // Centers
01277     X2center = Xcenter + dx - 1;
01278     Y2center = Ycenter + dy - 1;
01279 
01280     SDL_Rect area;
01281     area.x = x0; 
01282     area.y = Ycenter;
01283     area.w = w; 
01284     area.h = dy;
01285     
01286     SDL_FillRect(screen, &area, color);
01287     color = color *256 + 255;
01288     
01289     // because of = there are some lines drawn twice
01290     while (x <= corner) 
01291     {
01292 
01293         line(screen, Xcenter - x,   Ycenter - corner, 
01294                      X2center + x,  Ycenter - corner, color);
01295         line(screen, Xcenter - x,   Y2center + corner, 
01296                      X2center + x,  Y2center + corner, color);
01297         line(screen, Xcenter - corner,      Ycenter - x, 
01298                      X2center + corner,     Ycenter - x, color);
01299         line(screen, Xcenter - corner,      Y2center + x, 
01300                      X2center + corner,     Y2center + x, color);
01301         
01302 
01303         if (d >= 0) 
01304         {
01305             d += diagonalInc;
01306             diagonalInc += 8;
01307             --corner;
01308         } 
01309         else 
01310         {
01311             d += rightInc;
01312             diagonalInc += 4;
01313         }
01314         rightInc += 4;
01315         ++x;
01316     }/*while*/
01317 }
01318 
01319 #define R(color) (((color)&0xff0000)>>16)
01320 #define G(color) (((color)&0x00ff00)>>8)
01321 #define B(color) (((color)&0x0000ff))
01322 // following to methods stolen from aedGUI!
01323 void SDLMain::horizgradient(SDL_Surface * surf, SDL_Rect & gradRect, int c1, int c2, Uint8 alpha)
01324 {
01325     int x, width, height;
01326     Uint8 r1=R(c1), g1 = G(c1), b1 = B(c1);
01327     Uint8 r2=R(c2), g2 = G(c2), b2 = B(c2);
01328     Uint8 r, g, b;
01329     SDL_Rect dest;
01330     Uint32 pixelcolor;
01331 
01332     width = gradRect.w;
01333     height = gradRect.h;
01334 
01335 
01336     // Some optimization:
01337     if ((r1 == r2) && (g1 == g2) && (b1 == b2))
01338     {
01339         SDL_FillRect(surf, NULL, SDL_MapRGBA(surf->format, r1, g1, b1, alpha));
01340     }
01341     else
01342     {
01343         for(x = 0; x < width; x++)
01344         {
01345             r = (r2 * x / width) + (r1 * (width - x) / width);
01346             g = (g2 * x / width) + (g1 * (width - x) / width);
01347             b = (b2 * x / width) + (b1 * (width - x) / width);
01348 
01349             dest.x = gradRect.x + x;
01350             dest.y = gradRect.y;
01351             dest.w = 1;
01352             dest.h = height;
01353 
01354             pixelcolor = SDL_MapRGBA(surf->format, r, g, b, alpha);
01355             SDL_FillRect(surf, &dest, pixelcolor);
01356         }
01357     }
01358 }
01359 
01360 void SDLMain::vertgradient(SDL_Surface * surf, SDL_Rect & gradRect, int c1, int c2, Uint8 alpha)
01361 {
01362     int y, width, height;
01363     Uint8 r1=R(c1), g1 = G(c1), b1 = B(c1);
01364     Uint8 r2=R(c2), g2 = G(c2), b2 = B(c2);
01365     Uint8 r, g, b;
01366     SDL_Rect dest;
01367     Uint32 pixelcolor;
01368 
01369     width = gradRect.w;
01370     height = gradRect.h;
01371 
01372 
01373     // Some optimization:
01374     if ((r1 == r2) && (g1 == g2) && (b1 == b2))
01375     {
01376         SDL_FillRect(surf, NULL, SDL_MapRGBA(surf->format, r1, g1, b1, alpha));
01377     }
01378     else
01379     {
01380         for(y = 0; y < height; y++)
01381         {
01382             r = (r2 * y / height) + (r1 * (height - y) / height);
01383             g = (g2 * y / height) + (g1 * (height - y) / height);
01384             b = (b2 * y / height) + (b1 * (height - y) / height);
01385 
01386             dest.x = gradRect.x;
01387             dest.y = gradRect.y + y;
01388             dest.w = width;
01389             dest.h = 1;
01390 
01391             pixelcolor = SDL_MapRGBA(surf->format, r, g, b, alpha);
01392             SDL_FillRect(surf, &dest, pixelcolor);
01393         }
01394     }
01395 }

Generated on Wed Jul 14 00:43:43 2004 for CSLib by doxygen 1.3.6