00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
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;
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()
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
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
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
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
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
00372
00373
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
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 {
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
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: {
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
00624
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
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:{
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:{
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:{
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:{
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
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
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
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
00890
00891 if (!(clipLine(dst, &x1, &y1, &x2, &y2)))
00892 {
00893 LOG_EXIT
00894 return (0);
00895 }
00896
00897
00898
00899
00900 dx = x2 - x1;
00901 dy = y2 - y1;
00902 sx = (dx >= 0) ? 1 : -1;
00903 sy = (dy >= 0) ? 1 : -1;
00904
00905
00906 if (SDL_MUSTLOCK(dst))
00907 {
00908 if (SDL_LockSurface(dst) < 0)
00909 {
00910 LOG_EXIT
00911 return (-1);
00912 }
00913 }
00914
00915
00916
00917
00918 if ((color & 255) == 255)
00919 {
00920
00921
00922
00923
00924
00925
00926
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
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
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:
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
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
01073 if (SDL_MUSTLOCK(dst))
01074 {
01075 SDL_UnlockSurface(dst);
01076 }
01077 LOG_EXIT
01078 return (0);
01079 }
01080
01081
01082
01083
01084
01085
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
01108
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
01138 dx = w - (corner << 1);
01139 dy = h - (corner << 1);
01140 Xcenter = x0 + corner;
01141 Ycenter = y0 + corner;
01142
01143
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
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
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
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
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
01243
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
01271 dx = w - (corner << 1);
01272 Xcenter = x0 + corner;
01273 dy = h - (corner << 1);
01274 Ycenter = y0 + corner;
01275
01276
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
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 }
01317 }
01318
01319 #define R(color) (((color)&0xff0000)>>16)
01320 #define G(color) (((color)&0x00ff00)>>8)
01321 #define B(color) (((color)&0x0000ff))
01322
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
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
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 }