Mercurial > fife-parpg
changeset 603:739d8a43d771
* Fixed a bug in glimage.cpp. Now scale_x and scale_y is used.
* Fixed a bug in sdlimage.cpp. Removed a SDL_SetAlpha() call, which had triggered a segfault.
* Added Zoom support to SDL.
author | helios2000@33b003aa-7bff-0310-803a-e67f0ece8222 |
---|---|
date | Wed, 08 Sep 2010 13:47:16 +0000 |
parents | 2032ec27b851 |
children | da83338b6913 |
files | engine/core/video/opengl/glimage.cpp engine/core/video/sdl/sdlimage.cpp engine/core/video/sdl/sdlimage.h |
diffstat | 3 files changed, 171 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- a/engine/core/video/opengl/glimage.cpp Mon Sep 06 16:43:24 2010 +0000 +++ b/engine/core/video/opengl/glimage.cpp Wed Sep 08 13:47:16 2010 +0000 @@ -109,10 +109,10 @@ for (unsigned int i = 0; i < m_cols; ++i) { if (i == m_cols-1) { col_fill_ratio = m_last_col_fill_ratio; - target.w = static_cast<int>(round(scale_y*m_last_col_width*m_last_col_fill_ratio)); + target.w = static_cast<int>(round(scale_x*m_last_col_width*m_last_col_fill_ratio)); } else { col_fill_ratio = 1.0; - target.w = static_cast<int>(round(scale_y*m_chunk_size)); + target.w = static_cast<int>(round(scale_x*m_chunk_size)); } if (i > 0) { target.x = prev.x + prev.w;
--- a/engine/core/video/sdl/sdlimage.cpp Mon Sep 06 16:43:24 2010 +0000 +++ b/engine/core/video/sdl/sdlimage.cpp Wed Sep 08 13:47:16 2010 +0000 @@ -55,10 +55,16 @@ m_finalized = false; m_isalphaoptimized = false; m_colorkey = RenderBackend::instance()->getColorKey(); + m_scale_x = 1.0; + m_scale_y = 1.0; + m_zoom_surface = NULL; } - SDLImage::~SDLImage() { } - + SDLImage::~SDLImage() { + if (m_zoom_surface) { + SDL_FreeSurface(m_zoom_surface); + } + } void SDL_BlitSurfaceWithAlpha( const SDL_Surface* src, const SDL_Rect* srcRect, SDL_Surface* dst, SDL_Rect* dstRect, unsigned char alpha ) { @@ -192,6 +198,121 @@ SDL_UnlockSurface( dst ); } + void zoomSurface(SDL_Surface* src, SDL_Surface* dst) { + SDL_Color* src_pointer = (SDL_Color*)src->pixels; + SDL_Color* src_help_pointer = src_pointer; + SDL_Color* dst_pointer = (SDL_Color*)dst->pixels; + + int x, y, *sx_ca, *sy_ca; + int dst_gap = dst->pitch - dst->w * dst->format->BytesPerPixel; + int sx = static_cast<int>(0xffff * src->w / dst->w); + int sy = static_cast<int>(0xffff * src->h / dst->h); + int sx_c = 0; + int sy_c = 0; + + // Allocates memory and calculates row wide&height + int* sx_a = (int*)malloc((dst->w + 1) * sizeof(Uint32)); + if (sx_a == NULL) { + return; + } else { + sx_ca = sx_a; + for (; x <= dst->w; x++) { + *sx_ca = sx_c; + sx_ca++; + sx_c &= 0xffff; + sx_c += sx; + } + } + int* sy_a = (int*)malloc((dst->h + 1) * sizeof(Uint32)); + if (sy_a == NULL) { + free(sx_a); + return; + } else { + sy_ca = sy_a; + for (; y <= dst->h; y++) { + *sy_ca = sy_c; + sy_ca++; + sy_c &= 0xffff; + sy_c += sy; + } + sy_ca = sy_a; + } + + // Transfers the image data + + if(SDL_MUSTLOCK(src)) + SDL_LockSurface(src); + if(SDL_MUSTLOCK(dst)) + SDL_LockSurface(dst); + + for (y = 0; y < dst->h; y++) { + src_pointer = src_help_pointer; + sx_ca = sx_a; + for (x = 0; x < dst->w; x++) { + *dst_pointer = *src_pointer; + sx_ca++; + src_pointer += (*sx_ca >> 16); + dst_pointer++; + } + sy_ca++; + src_help_pointer = (SDL_Color*)((Uint8*)src_help_pointer + (*sy_ca >> 16) * src->pitch); + dst_pointer = (SDL_Color*)((Uint8*)dst_pointer + dst_gap); + } + + if(SDL_MUSTLOCK(dst)) + SDL_UnlockSurface(dst); + if(SDL_MUSTLOCK(src)) + SDL_UnlockSurface(src); + + // Free memory + free(sx_a); + free(sy_a); + } + + SDL_Surface* getZoomedSurface(SDL_Surface * src, double zoomx, double zoomy) { + if (src == NULL) + return NULL; + + SDL_Surface *zoom_src; + SDL_Surface *zoom_dst; + int dst_w = static_cast<int>(round(src->w * zoomx)); + int dst_h = static_cast<int>(round(src->h * zoomy)); + if (dst_w < 1) + dst_w = 1; + if (dst_h < 1) + dst_h = 1; + + // If source surface has no alpha channel then convert it + if (src->format->Amask == 0) { + Uint32 rmask, gmask, bmask, amask; + #if SDL_BYTEORDER == SDL_BIG_ENDIAN + rmask = 0xff000000; gmask = 0x00ff0000; bmask = 0x0000ff00; amask = 0x000000ff; + #else + rmask = 0x000000ff; gmask = 0x0000ff00; bmask = 0x00ff0000; amask = 0xff000000; + #endif + + zoom_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, + rmask, gmask, + bmask, amask); + SDL_BlitSurface(src, NULL, zoom_src, NULL); + } else { + zoom_src = src; + } + // Create destination surface + zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_w, dst_h, 32, + zoom_src->format->Rmask, zoom_src->format->Gmask, + zoom_src->format->Bmask, zoom_src->format->Amask); + + // Zoom surface + zoomSurface(zoom_src, zoom_dst); + + return zoom_dst; + } + + bool nearlyEqual(float a, float b) { + return ABS(a - b) <= 0.00001; + } + void SDLImage::render(const Rect& rect, SDL_Surface* screen, unsigned char alpha) { if (alpha == 0) { return; @@ -209,20 +330,59 @@ r.w = rect.w; r.h = rect.h; + float scale_x = static_cast<float>(rect.w) / static_cast<float>(m_surface->w); + float scale_y = static_cast<float>(rect.h) / static_cast<float>(m_surface->h); + bool zoomed = false; + bool equal = false; + + if (!nearlyEqual(scale_x, 1.0) && !nearlyEqual(scale_y, 1.0)) { + zoomed = true; + if(nearlyEqual(m_scale_x, scale_x) && nearlyEqual(m_scale_y, scale_y)) { + equal = true; + } else { + m_scale_x = scale_x; + m_scale_y = scale_y; + } + } + if (m_surface->format->Amask == 0) { // Image has no alpha channel. This allows us to use the per-surface alpha. if (m_last_alpha != alpha) { m_last_alpha = alpha; SDL_SetAlpha(m_surface, SDL_SRCALPHA | SDL_RLEACCEL, alpha); } - SDL_BlitSurface(m_surface, 0, surface, &r); + if (!zoomed) { + SDL_BlitSurface(m_surface, 0, surface, &r); + } else if (equal && m_zoom_surface) { + SDL_BlitSurface(m_zoom_surface, 0, surface, &r); + } else { + SDL_FreeSurface(m_zoom_surface); + m_zoom_surface = getZoomedSurface(m_surface, m_scale_x, m_scale_y); + SDL_BlitSurface(m_zoom_surface, 0, surface, &r); + } } else { if( 255 != alpha ) { // Special blitting routine with alpha blending: // dst.rgb = ( src.rgb * src.a * alpha ) + ( dst.rgb * (255 - ( src.a * alpha ) ) ); - SDL_BlitSurfaceWithAlpha( m_surface, 0, surface, &r, alpha ); + if (!zoomed) { + SDL_BlitSurfaceWithAlpha( m_surface, 0, surface, &r, alpha ); + } else if (equal && m_zoom_surface) { + SDL_BlitSurfaceWithAlpha(m_zoom_surface, 0, surface, &r, alpha ); + } else { + SDL_FreeSurface(m_zoom_surface); + m_zoom_surface = getZoomedSurface(m_surface, m_scale_x, m_scale_y); + SDL_BlitSurfaceWithAlpha(m_zoom_surface, 0, surface, &r, alpha ); + } } else { - SDL_BlitSurface(m_surface, 0, surface, &r); + if (!zoomed) { + SDL_BlitSurface(m_surface, 0, surface, &r); + } else if (equal && m_zoom_surface) { + SDL_BlitSurface(m_zoom_surface, 0, surface, &r); + } else { + SDL_FreeSurface(m_zoom_surface); + m_zoom_surface = getZoomedSurface(m_surface, m_scale_x, m_scale_y); + SDL_BlitSurface(m_zoom_surface, 0, surface, &r); + } } } } @@ -236,8 +396,6 @@ Uint32 key = SDL_MapRGB(m_surface->format, m_colorkey.r, m_colorkey.g, m_colorkey.b); if (m_surface->format->Amask == 0) { - SDL_SetAlpha(m_surface, SDL_SRCALPHA | SDL_RLEACCEL, 255); - // only use color key if feature is enabled if (RenderBackend::instance()->isColorKeyEnabled()) { SDL_SetColorKey(m_surface, SDL_SRCCOLORKEY, key);
--- a/engine/core/video/sdl/sdlimage.h Mon Sep 06 16:43:24 2010 +0000 +++ b/engine/core/video/sdl/sdlimage.h Wed Sep 08 13:47:16 2010 +0000 @@ -71,6 +71,10 @@ // Is the surface already optimized for rendering bool m_finalized; SDL_Color m_colorkey; + // Surface for zoom + SDL_Surface* m_zoom_surface; + float m_scale_x; + float m_scale_y; }; }