00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <cassert>
00024 #include <iostream>
00025
00026
00027
00028
00029
00030
00031
00032 #include "util/log/logger.h"
00033 #include "util/structures/rect.h"
00034 #include "video/renderbackend.h"
00035
00036 #include "renderbackendsdl.h"
00037 #include "sdlblendingfunctions.h"
00038 #include "sdlimage.h"
00039
00040 namespace FIFE {
00041 static Logger _log(LM_VIDEO);
00042
00043 SDLImage::SDLImage(SDL_Surface* surface):
00044 Image(surface) {
00045 resetSdlimage();
00046 }
00047
00048 SDLImage::SDLImage(const uint8_t* data, unsigned int width, unsigned int height):
00049 Image(data, width, height) {
00050 resetSdlimage();
00051 }
00052
00053 void SDLImage::resetSdlimage() {
00054 m_last_alpha = 255;
00055 m_finalized = false;
00056 m_isalphaoptimized = false;
00057 m_colorkey = RenderBackend::instance()->getColorKey();
00058 m_scale_x = 1.0;
00059 m_scale_y = 1.0;
00060 m_zoom_surface = NULL;
00061 }
00062
00063 SDLImage::~SDLImage() {
00064 if (m_zoom_surface) {
00065 SDL_FreeSurface(m_zoom_surface);
00066 }
00067 }
00068
00069 void SDL_BlitSurfaceWithAlpha( const SDL_Surface* src, const SDL_Rect* srcRect,
00070 SDL_Surface* dst, SDL_Rect* dstRect, unsigned char alpha ) {
00071 if( 0 == alpha ) {
00072 return;
00073 }
00074
00075 int screenX, screenY;
00076 if( dstRect ) {
00077 screenX = dstRect->x;
00078 screenY = dstRect->y;
00079 } else {
00080 screenX = dst->clip_rect.x;
00081 screenY = dst->clip_rect.y;
00082 }
00083
00084 int width, height, tX, tY;
00085 if( srcRect ) {
00086 tX = srcRect->x;
00087 tY = srcRect->y;
00088 width = srcRect->w;
00089 height = srcRect->h;
00090 } else {
00091 tX = src->clip_rect.x;
00092 tY = src->clip_rect.y;
00093 width = src->clip_rect.w;
00094 height = src->clip_rect.h;
00095 }
00096
00097
00098 if( ( screenX >= ( dst->clip_rect.x + dst->clip_rect.w ) ) ||
00099 ( screenY >= ( dst->clip_rect.y + dst->clip_rect.h ) ) ||
00100 ( ( screenX + width ) <= dst->clip_rect.x ) ||
00101 ( ( screenY + height ) <= dst->clip_rect.y ) ) {
00102 return;
00103 }
00104
00105 if( screenX < dst->clip_rect.x ) {
00106 int dX = dst->clip_rect.x - screenX;
00107 screenX += dX;
00108 width -= dX;
00109 tX += dX;
00110 }
00111
00112 if( ( screenX + width ) > ( dst->clip_rect.x + dst->clip_rect.w ) ) {
00113 int dX = ( screenX + width ) - ( dst->clip_rect.x + dst->clip_rect.w );
00114 width -= dX;
00115 }
00116
00117 if( screenY < dst->clip_rect.y ) {
00118 int dY = dst->clip_rect.y - screenY;
00119 screenY += dY;
00120 height -= dY;
00121 tY += dY;
00122 }
00123
00124 if( ( screenY + height ) > ( dst->clip_rect.y + dst->clip_rect.h ) ) {
00125 int dY = ( screenY + height ) - ( dst->clip_rect.y + dst->clip_rect.h );
00126 height -= dY;
00127 }
00128
00129 if( ( 0 >= height ) || ( 0 >= width ) ) {
00130 return;
00131 }
00132
00133 SDL_LockSurface( dst );
00134
00135 unsigned char* srcData = reinterpret_cast< unsigned char* > ( src->pixels );
00136 unsigned char* dstData = reinterpret_cast< unsigned char* > ( dst->pixels );
00137
00138
00139 srcData += tY * src->pitch + tX * src->format->BytesPerPixel;
00140 dstData += screenY * dst->pitch + screenX * dst->format->BytesPerPixel;
00141
00142 switch( src->format->BitsPerPixel ) {
00143 case 32: {
00144 switch( dst->format->BitsPerPixel ) {
00145 case 16: {
00146 if( 0xFFFF == ( dst->format->Rmask | dst->format->Gmask | dst->format->Bmask ) ) {
00147 for( int y = height; y > 0; --y ) {
00148 SDL_BlendRow_RGBA8_to_RGB565( srcData, dstData, alpha, width );
00149 srcData += src->pitch;
00150 dstData += dst->pitch;
00151 }
00152 }
00153 }
00154 break;
00155
00156 case 24: {
00157 for( int y = height; y > 0; --y ) {
00158 SDL_BlendRow_RGBA8_to_RGB8( srcData, dstData, alpha, width );
00159 srcData += src->pitch;
00160 dstData += dst->pitch;
00161 }
00162 }
00163 break;
00164
00165 case 32: {
00166 for( int y = height; y > 0; --y ) {
00167 SDL_BlendRow_RGBA8_to_RGBA8( srcData, dstData, alpha, width );
00168 srcData += src->pitch;
00169 dstData += dst->pitch;
00170 }
00171 }
00172 break;
00173
00174 default:
00175 break;
00176 }
00177 }
00178 break;
00179
00180 case 16: {
00181 if( 0x000F == src->format->Amask ) {
00182 if( ( 16 == dst->format->BitsPerPixel ) &&
00183 ( 0xFFFF == ( dst->format->Rmask | dst->format->Gmask | dst->format->Bmask ) ) ) {
00184 for( int y = height; y > 0; --y ) {
00185 SDL_BlendRow_RGBA4_to_RGB565( srcData, dstData, alpha, width );
00186 srcData += src->pitch;
00187 dstData += dst->pitch;
00188 }
00189 }
00190 }
00191 }
00192 break;
00193
00194 default:
00195 break;
00196 }
00197
00198 SDL_UnlockSurface( dst );
00199 }
00200
00201 void zoomSurface(SDL_Surface* src, SDL_Surface* dst) {
00202 SDL_Color* src_pointer = (SDL_Color*)src->pixels;
00203 SDL_Color* src_help_pointer = src_pointer;
00204 SDL_Color* dst_pointer = (SDL_Color*)dst->pixels;
00205
00206 int x, y, *sx_ca, *sy_ca;
00207 int dst_gap = dst->pitch - dst->w * dst->format->BytesPerPixel;
00208 int sx = static_cast<int>(0xffff * src->w / dst->w);
00209 int sy = static_cast<int>(0xffff * src->h / dst->h);
00210 int sx_c = 0;
00211 int sy_c = 0;
00212
00213
00214 int* sx_a = (int*)malloc((dst->w + 1) * sizeof(Uint32));
00215 if (sx_a == NULL) {
00216 return;
00217 } else {
00218 sx_ca = sx_a;
00219 for (x = 0; x <= dst->w; x++) {
00220 *sx_ca = sx_c;
00221 sx_ca++;
00222 sx_c &= 0xffff;
00223 sx_c += sx;
00224 }
00225 }
00226 int* sy_a = (int*)malloc((dst->h + 1) * sizeof(Uint32));
00227 if (sy_a == NULL) {
00228 free(sx_a);
00229 return;
00230 } else {
00231 sy_ca = sy_a;
00232 for (y = 0; y <= dst->h; y++) {
00233 *sy_ca = sy_c;
00234 sy_ca++;
00235 sy_c &= 0xffff;
00236 sy_c += sy;
00237 }
00238 sy_ca = sy_a;
00239 }
00240
00241
00242
00243 if(SDL_MUSTLOCK(src))
00244 SDL_LockSurface(src);
00245 if(SDL_MUSTLOCK(dst))
00246 SDL_LockSurface(dst);
00247
00248 for (y = 0; y < dst->h; y++) {
00249 src_pointer = src_help_pointer;
00250 sx_ca = sx_a;
00251 for (x = 0; x < dst->w; x++) {
00252 *dst_pointer = *src_pointer;
00253 sx_ca++;
00254 src_pointer += (*sx_ca >> 16);
00255 dst_pointer++;
00256 }
00257 sy_ca++;
00258 src_help_pointer = (SDL_Color*)((Uint8*)src_help_pointer + (*sy_ca >> 16) * src->pitch);
00259 dst_pointer = (SDL_Color*)((Uint8*)dst_pointer + dst_gap);
00260 }
00261
00262 if(SDL_MUSTLOCK(dst))
00263 SDL_UnlockSurface(dst);
00264 if(SDL_MUSTLOCK(src))
00265 SDL_UnlockSurface(src);
00266
00267
00268 free(sx_a);
00269 free(sy_a);
00270 }
00271
00272 SDL_Surface* getZoomedSurface(SDL_Surface * src, double zoomx, double zoomy) {
00273 if (src == NULL)
00274 return NULL;
00275
00276 SDL_Surface *zoom_src;
00277 SDL_Surface *zoom_dst;
00278 int dst_w = static_cast<int>(round(src->w * zoomx));
00279 int dst_h = static_cast<int>(round(src->h * zoomy));
00280 if (dst_w < 1)
00281 dst_w = 1;
00282 if (dst_h < 1)
00283 dst_h = 1;
00284
00285
00286 if (src->format->Amask == 0) {
00287 zoom_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
00288 RMASK, GMASK,
00289 BMASK, AMASK);
00290 SDL_BlitSurface(src, NULL, zoom_src, NULL);
00291 } else {
00292 zoom_src = src;
00293 }
00294
00295 zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_w, dst_h, 32,
00296 zoom_src->format->Rmask, zoom_src->format->Gmask,
00297 zoom_src->format->Bmask, zoom_src->format->Amask);
00298
00299
00300 zoomSurface(zoom_src, zoom_dst);
00301
00302 return zoom_dst;
00303 }
00304
00305 bool nearlyEqual(float a, float b) {
00306 return ABS(a - b) <= 0.00001;
00307 }
00308
00309 void SDLImage::render(const Rect& rect, SDL_Surface* screen, unsigned char alpha) {
00310 if (alpha == 0) {
00311 return;
00312 }
00313
00314 if (rect.right() < 0 || rect.x > static_cast<int>(screen->w) || rect.bottom() < 0 || rect.y > static_cast<int>(screen->h)) {
00315 return;
00316 }
00317 finalize();
00318
00319 SDL_Surface* surface = screen;
00320 SDL_Rect r;
00321 r.x = rect.x;
00322 r.y = rect.y;
00323 r.w = rect.w;
00324 r.h = rect.h;
00325
00326 float scale_x = static_cast<float>(rect.w) / static_cast<float>(m_surface->w);
00327 float scale_y = static_cast<float>(rect.h) / static_cast<float>(m_surface->h);
00328 bool zoomed = false;
00329 bool equal = false;
00330
00331 if (!nearlyEqual(scale_x, 1.0) && !nearlyEqual(scale_y, 1.0)) {
00332 zoomed = true;
00333 if(nearlyEqual(m_scale_x, scale_x) && nearlyEqual(m_scale_y, scale_y)) {
00334 equal = true;
00335 } else {
00336 m_scale_x = scale_x;
00337 m_scale_y = scale_y;
00338 }
00339 }
00340
00341 if (m_surface->format->Amask == 0) {
00342
00343 if (m_last_alpha != alpha) {
00344 m_last_alpha = alpha;
00345 SDL_SetAlpha(m_surface, SDL_SRCALPHA | SDL_RLEACCEL, alpha);
00346 }
00347 if (!zoomed) {
00348 SDL_BlitSurface(m_surface, 0, surface, &r);
00349 } else if (equal && m_zoom_surface) {
00350 SDL_BlitSurface(m_zoom_surface, 0, surface, &r);
00351 } else {
00352 SDL_FreeSurface(m_zoom_surface);
00353 m_zoom_surface = getZoomedSurface(m_surface, m_scale_x, m_scale_y);
00354 SDL_BlitSurface(m_zoom_surface, 0, surface, &r);
00355 }
00356 } else {
00357 if( 255 != alpha ) {
00358
00359
00360 if (!zoomed) {
00361 SDL_BlitSurfaceWithAlpha( m_surface, 0, surface, &r, alpha );
00362 } else if (equal && m_zoom_surface) {
00363 SDL_BlitSurfaceWithAlpha(m_zoom_surface, 0, surface, &r, alpha );
00364 } else {
00365 SDL_FreeSurface(m_zoom_surface);
00366 m_zoom_surface = getZoomedSurface(m_surface, m_scale_x, m_scale_y);
00367 SDL_BlitSurfaceWithAlpha(m_zoom_surface, 0, surface, &r, alpha );
00368 }
00369 } else {
00370 if (!zoomed) {
00371 SDL_BlitSurface(m_surface, 0, surface, &r);
00372 } else if (equal && m_zoom_surface) {
00373 SDL_BlitSurface(m_zoom_surface, 0, surface, &r);
00374 } else {
00375 SDL_FreeSurface(m_zoom_surface);
00376 m_zoom_surface = getZoomedSurface(m_surface, m_scale_x, m_scale_y);
00377 SDL_BlitSurface(m_zoom_surface, 0, surface, &r);
00378 }
00379 }
00380 }
00381 }
00382
00383 void SDLImage::finalize() {
00384 if( m_finalized ) {
00385 return;
00386 }
00387 m_finalized = true;
00388 SDL_Surface *old_surface = m_surface;
00389 Uint32 key = SDL_MapRGB(m_surface->format, m_colorkey.r, m_colorkey.g, m_colorkey.b);
00390
00391 if (m_surface->format->Amask == 0) {
00392
00393 if (RenderBackend::instance()->isColorKeyEnabled()) {
00394 SDL_SetColorKey(m_surface, SDL_SRCCOLORKEY, key);
00395 }
00396
00397 m_surface = SDL_DisplayFormat(m_surface);
00398 } else {
00399 RenderBackendSDL* be = static_cast<RenderBackendSDL*>(RenderBackend::instance());
00400 m_isalphaoptimized = be->isAlphaOptimizerEnabled();
00401 if( m_isalphaoptimized ) {
00402 m_surface = optimize(m_surface);
00403 } else {
00404 SDL_SetAlpha(m_surface, SDL_SRCALPHA, 255);
00405
00406
00407 if (RenderBackend::instance()->isColorKeyEnabled()) {
00408 SDL_SetColorKey(m_surface, SDL_SRCCOLORKEY, key);
00409 }
00410
00411 m_surface = SDL_DisplayFormatAlpha(m_surface);
00412 }
00413 }
00414 SDL_FreeSurface(old_surface);
00415 }
00416
00417 SDL_Surface* SDLImage::optimize(SDL_Surface* src) {
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428 int transparent = 0;
00429 int opaque = 0;
00430 int semitransparent = 0;
00431 int alphasum = 0;
00432 int alphasquaresum = 0;
00433 bool colors[(1 << 12)];
00434 memset(colors, 0, (1 << 12) * sizeof(bool));
00435
00436 int bpp = src->format->BytesPerPixel;
00437 if(SDL_MUSTLOCK(src)) {
00438 SDL_LockSurface(src);
00439 }
00440
00441
00442
00443
00444 for(int y = 0;y < src->h;y++) {
00445 for(int x = 0;x < src->w;x++) {
00446 Uint8 *pixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp;
00447 Uint32 mapped = 0;
00448 switch(bpp) {
00449 case 1:
00450 mapped = *pixel;
00451 break;
00452 case 2:
00453 mapped = *(Uint16 *)pixel;
00454 break;
00455 case 3:
00456 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
00457 mapped |= pixel[0] << 16;
00458 mapped |= pixel[1] << 8;
00459 mapped |= pixel[2] << 0;
00460 #else
00461 mapped |= pixel[0] << 0;
00462 mapped |= pixel[1] << 8;
00463 mapped |= pixel[2] << 16;
00464 #endif
00465 break;
00466 case 4:
00467 mapped = *(Uint32 *)pixel;
00468 break;
00469 }
00470 Uint8 red, green, blue, alpha;
00471 SDL_GetRGBA(mapped, src->format, &red, &green, &blue, &alpha);
00472 if(alpha < 16) {
00473 transparent++;
00474 } else if (alpha > 240) {
00475 opaque++;
00476 alphasum += alpha;
00477 alphasquaresum += alpha*alpha;
00478 } else {
00479 semitransparent++;
00480 alphasum += alpha;
00481 alphasquaresum += alpha*alpha;
00482 }
00483
00484 if( alpha != 0 ) {
00485 colors[((red & 0xf0) << 4) | (green & 0xf0) | ((blue & 0xf0) >> 4)] = true;
00486 }
00487 }
00488 }
00489 int avgalpha = (opaque + semitransparent) ? alphasum / (opaque + semitransparent) : 0;
00490 int alphavariance = 0;
00491
00492 if(SDL_MUSTLOCK(src)) {
00493 SDL_UnlockSurface(src);
00494 }
00495 alphasquaresum /= (opaque + semitransparent) ? (opaque + semitransparent) : 1;
00496 alphavariance = alphasquaresum - avgalpha*avgalpha;
00497 if(semitransparent > ((transparent + opaque + semitransparent) / 8)
00498 && alphavariance > 16) {
00499 FL_DBG(_log, LMsg("sdlimage")
00500 << "Trying to alpha-optimize image. FAILED: real alpha usage. "
00501 << " alphavariance=" << alphavariance
00502 << " total=" << (transparent + opaque + semitransparent)
00503 << " semitransparent=" << semitransparent
00504 << "(" << (float(semitransparent)/(transparent + opaque + semitransparent))
00505 << ")");
00506 return SDL_DisplayFormatAlpha(src);
00507 }
00508
00509
00510 int keycolor = -1;
00511 for(int i = 0;i < (1 << 12);i++) {
00512 if(!colors[i]) {
00513 keycolor = i;
00514 break;
00515 }
00516 }
00517 if(keycolor == -1) {
00518 FL_DBG(_log, LMsg("sdlimage") << "Trying to alpha-optimize image. FAILED: no free color");
00519 return SDL_DisplayFormatAlpha(src);
00520 }
00521
00522 SDL_Surface *dst = SDL_CreateRGBSurface(src->flags & ~(SDL_SRCALPHA) | SDL_SWSURFACE,
00523 src->w, src->h,
00524 src->format->BitsPerPixel,
00525 src->format->Rmask, src->format->Gmask,
00526 src->format->Bmask, 0);
00527 bpp = dst->format->BytesPerPixel;
00528
00529 Uint32 key = SDL_MapRGB(dst->format, m_colorkey.r, m_colorkey.g, m_colorkey.b);
00530
00531
00532 if (!RenderBackend::instance()->isColorKeyEnabled()) {
00533 key = SDL_MapRGB(dst->format,
00534 (((keycolor & 0xf00) >> 4) | 0xf),
00535 ((keycolor & 0xf0) | 0xf),
00536 (((keycolor & 0xf) << 4) | 0xf));
00537 }
00538
00539 if(SDL_MUSTLOCK(src)) {
00540 SDL_LockSurface(src);
00541 }
00542 if(SDL_MUSTLOCK(dst)) {
00543 SDL_LockSurface(dst);
00544 }
00545 for(int y = 0;y < dst->h;y++) {
00546 for(int x = 0;x < dst->w;x++) {
00547 Uint8 *srcpixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp;
00548 Uint8 *dstpixel = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
00549 Uint32 mapped = 0;
00550 switch(bpp) {
00551 case 1:
00552 mapped = *srcpixel;
00553 break;
00554 case 2:
00555 mapped = *(Uint16 *)srcpixel;
00556 break;
00557 case 3:
00558 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
00559 mapped |= srcpixel[0] << 16;
00560 mapped |= srcpixel[1] << 8;
00561 mapped |= srcpixel[2] << 0;
00562 #else
00563 mapped |= srcpixel[0] << 0;
00564 mapped |= srcpixel[1] << 8;
00565 mapped |= srcpixel[2] << 16;
00566 #endif
00567 break;
00568 case 4:
00569 mapped = *(Uint32 *)srcpixel;
00570 break;
00571 }
00572 Uint8 red, green, blue, alpha;
00573 SDL_GetRGBA(mapped, src->format, &red, &green, &blue, &alpha);
00574 if(alpha < (avgalpha / 4)) {
00575 mapped = key;
00576 } else {
00577 mapped = SDL_MapRGB(dst->format, red, green, blue);
00578 }
00579 switch(bpp) {
00580 case 1:
00581 *dstpixel = mapped;
00582 break;
00583 case 2:
00584 *(Uint16 *)dstpixel = mapped;
00585 break;
00586 case 3:
00587 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
00588 dstpixel[0] = (mapped >> 16) & 0xff;
00589 dstpixel[1] = (mapped >> 8) & 0xff;
00590 dstpixel[2] = (mapped >> 0) & 0xff;
00591 #else
00592 dstpixel[0] = (mapped >> 0) & 0xff;
00593 dstpixel[1] = (mapped >> 8) & 0xff;
00594 dstpixel[2] = (mapped >> 16) & 0xff;
00595 #endif
00596 break;
00597 case 4:
00598 *(Uint32 *)dstpixel = mapped;
00599 break;
00600 }
00601 }
00602 }
00603 if(SDL_MUSTLOCK(dst)) {
00604 SDL_UnlockSurface(dst);
00605 }
00606 if(SDL_MUSTLOCK(src)) {
00607 SDL_UnlockSurface(src);
00608 }
00609
00610
00611
00612
00613
00614
00615
00616 SDL_SetColorKey(dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, key);
00617 SDL_Surface *convert = SDL_DisplayFormat(dst);
00618 SDL_FreeSurface(dst);
00619 FL_DBG(_log, LMsg("sdlimage ")
00620 << "Trying to alpha-optimize image. SUCCESS: colorkey is " << key);
00621 return convert;
00622 }
00623
00624 bool SDLImage::putPixel(int x, int y, int r, int g, int b, int a) {
00625 if ((x < 0) || (x >= m_surface->w) || (y < 0) || (y >= m_surface->h)) {
00626 return false;
00627 }
00628
00629 int bpp = m_surface->format->BytesPerPixel;
00630 SDL_LockSurface(m_surface);
00631 Uint8* p = (Uint8*)m_surface->pixels + y * m_surface->pitch + x * bpp;
00632 Uint32 pixel = SDL_MapRGB(m_surface->format, r, g, b);
00633 switch(bpp)
00634 {
00635 case 1:
00636 *p = pixel;
00637 break;
00638
00639 case 2:
00640 *(Uint16 *)p = pixel;
00641 break;
00642
00643 case 3:
00644 if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
00645 p[0] = (pixel >> 16) & 0xff;
00646 p[1] = (pixel >> 8) & 0xff;
00647 p[2] = pixel & 0xff;
00648 }
00649 else {
00650 p[0] = pixel & 0xff;
00651 p[1] = (pixel >> 8) & 0xff;
00652 p[2] = (pixel >> 16) & 0xff;
00653 }
00654 break;
00655
00656 case 4:
00657 *(Uint32 *)p = pixel;
00658 break;
00659 }
00660 SDL_UnlockSurface(m_surface);
00661 return true;
00662 }
00663
00664 void SDLImage::drawLine(const Point& p1, const Point& p2, int r, int g, int b, int a) {
00665
00666 int x1 = p1.x;
00667 int x2 = p2.x;
00668 int y1 = p1.y;
00669 int y2 = p2.y;
00670 int dx = ABS(x2 - x1);
00671 int dy = ABS(y2 - y1);
00672
00673 if (dx > dy) {
00674 if (x1 > x2) {
00675
00676 x1 ^= x2;
00677 x2 ^= x1;
00678 x1 ^= x2;
00679
00680
00681 y1 ^= y2;
00682 y2 ^= y1;
00683 y1 ^= y2;
00684 }
00685
00686 if (y1 < y2) {
00687 int y = y1;
00688 int p = 0;
00689
00690 for (int x = x1; x <= x2; x++) {
00691 putPixel(x, y, r, g, b, a);
00692 p += dy;
00693 if (p * 2 >= dx) {
00694 y++;
00695 p -= dx;
00696 }
00697 }
00698 }
00699 else {
00700 int y = y1;
00701 int p = 0;
00702
00703 for (int x = x1; x <= x2; x++) {
00704 putPixel(x, y, r, g, b, a);
00705
00706 p += dy;
00707 if (p * 2 >= dx) {
00708 y--;
00709 p -= dx;
00710 }
00711 }
00712 }
00713 }
00714 else {
00715 if (y1 > y2) {
00716
00717 y1 ^= y2;
00718 y2 ^= y1;
00719 y1 ^= y2;
00720
00721
00722 x1 ^= x2;
00723 x2 ^= x1;
00724 x1 ^= x2;
00725 }
00726
00727 if (x1 < x2) {
00728 int x = x1;
00729 int p = 0;
00730
00731 for (int y = y1; y <= y2; y++) {
00732 putPixel(x, y, r, g, b, a);
00733 p += dx;
00734 if (p * 2 >= dy) {
00735 x++;
00736 p -= dy;
00737 }
00738 }
00739 }
00740 else {
00741 int x = x1;
00742 int p = 0;
00743
00744 for (int y = y1; y <= y2; y++) {
00745 putPixel(x, y, r, g, b, a);
00746 p += dx;
00747 if (p * 2 >= dy) {
00748 x--;
00749 p -= dy;
00750 }
00751 }
00752 }
00753 }
00754 }
00755
00756 void SDLImage::drawTriangle(const Point& p1, const Point& p2, const Point& p3, int r, int g, int b, int a) {
00757 drawLine(p1, p2, r, g, b, a);
00758 drawLine(p2, p3, r, g, b, a);
00759 drawLine(p3, p1, r, g, b, a);
00760 }
00761
00762 void SDLImage::drawRectangle(const Point& p, uint16_t w, uint16_t h, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
00763 Point p1, p2, p3, p4;
00764
00765 p1.x = p.x;
00766 p1.y = p.y;
00767 p2.x = p.x+w;
00768 p2.y = p.y;
00769 p3.x = p.x+w;
00770 p3.y = p.y+h;
00771 p4.x = p.x;
00772 p4.y = p.y+h;
00773
00774 drawLine(p1, p2, r, g, b, a);
00775 drawLine(p2, p3, r, g, b, a);
00776 drawLine(p3, p4, r, g, b, a);
00777 drawLine(p4, p1, r, g, b, a);
00778 }
00779
00780 void SDLImage::fillRectangle(const Point& p, uint16_t w, uint16_t h, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
00781 SDL_Rect rect;
00782 rect.x = p.x;
00783 rect.y = p.y;
00784 rect.w = w;
00785 rect.h = h;
00786
00787 Uint32 color = SDL_MapRGBA(m_surface->format, r, g, b, a);
00788 SDL_FillRect(m_surface, &rect, color);
00789 }
00790
00791 void SDLImage::drawQuad(const Point& p1, const Point& p2, const Point& p3, const Point& p4, int r, int g, int b, int a) {
00792 drawLine(p1, p2, r, g, b, a);
00793 drawLine(p2, p3, r, g, b, a);
00794 drawLine(p3, p4, r, g, b, a);
00795 drawLine(p4, p1, r, g, b, a);
00796 }
00797
00798 void SDLImage::drawVertex(const Point& p, const uint8_t size, int r, int g, int b, int a){
00799 Point p1 = Point(p.x-size, p.y+size);
00800 Point p2 = Point(p.x+size, p.y+size);
00801 Point p3 = Point(p.x+size, p.y-size);
00802 Point p4 = Point(p.x-size, p.y-size);
00803
00804 drawLine(p1, p2, r, g, b, a);
00805 drawLine(p2, p3, r, g, b, a);
00806 drawLine(p3, p4, r, g, b, a);
00807 drawLine(p4, p1, r, g, b, a);
00808 }
00809
00810 void SDLImage::drawLightPrimitive(const Point& p, uint8_t intensity, float radius, int subdivisions, float xstretch, float ystretch, uint8_t red, uint8_t green, uint8_t blue) {
00811 }
00812
00813 void SDLImage::saveImage(const std::string& filename) {
00814 if(m_surface) {
00815 const unsigned int swidth = getWidth();
00816 const unsigned int sheight = getHeight();
00817 SDL_Surface *surface = NULL;
00818
00819 surface = SDL_CreateRGBSurface(SDL_SWSURFACE, swidth,
00820 sheight, 24,
00821 RMASK, GMASK, BMASK, 0);
00822
00823 if(surface == NULL) {
00824 return;
00825 }
00826
00827 SDL_BlitSurface(m_surface, NULL, surface, NULL);
00828
00829 saveAsPng(filename, *surface);
00830 SDL_FreeSurface(surface);
00831 }
00832 }
00833
00834 void SDLImage::setClipArea(const Rect& cliparea, bool clear) {
00835 SDL_Rect rect;
00836 rect.x = cliparea.x;
00837 rect.y = cliparea.y;
00838 rect.w = cliparea.w;
00839 rect.h = cliparea.h;
00840 SDL_SetClipRect(m_surface, &rect);
00841 if (clear) {
00842 SDL_FillRect(m_surface, &rect, 0x00);
00843 }
00844 }
00845 }