diff options
Diffstat (limited to 'src/resources/image.cpp')
-rw-r--r-- | src/resources/image.cpp | 77 |
1 files changed, 57 insertions, 20 deletions
diff --git a/src/resources/image.cpp b/src/resources/image.cpp index b217db683..8bf41aa4c 100644 --- a/src/resources/image.cpp +++ b/src/resources/image.cpp @@ -33,7 +33,11 @@ #include "utils/sdlcheckutils.h" +#ifdef USE_SDL2 +#include <SDL2_rotozoom.h> +#else #include <SDL_rotozoom.h> +#endif #include "debug.h" @@ -320,30 +324,63 @@ void Image::setAlpha(const float alpha) if (SDL_MUSTLOCK(mSDLSurface)) SDL_LockSurface(mSDLSurface); - // Precompute as much as possible - const int maxHeight = std::min((mBounds.y + mBounds.h), - mSDLSurface->h); - const int maxWidth = std::min((mBounds.x + mBounds.w), - mSDLSurface->w); - const int i1 = mBounds.y * mSDLSurface->w + mBounds.x; - const int i2 = (maxHeight - 1) * mSDLSurface->w + maxWidth - 1; - + const int bx = mBounds.x; + const int by = mBounds.y; + const int bw = mBounds.w; + const int bh = mBounds.h; + const int bxw = bx + bw; + const int sw = mSDLSurface->w; + const int maxHeight = std::min(by + bh, mSDLSurface->h); + const int maxWidth = std::min(bxw, sw); + const int i1 = by * sw + bx; const SDL_PixelFormat * const fmt = mSDLSurface->format; + const uint32_t amask = fmt->Amask; + const uint32_t invMask = ~fmt->Amask; + const uint8_t aloss = fmt->Aloss; + const uint8_t ashift = fmt->Ashift; - for (int i = i1; i <= i2; i++) + if (!bx && bxw == sw) { - // Only change the pixel if it was visible at load time... - const uint8_t sourceAlpha = mAlphaChannel[i]; - if (sourceAlpha > 0) + const int i2 = (maxHeight - 1) * sw + maxWidth - 1; + for (int i = i1; i <= i2; i++) { - const uint8_t a = static_cast<uint8_t>( - static_cast<float>(sourceAlpha) * mAlpha); - - uint32_t c = (static_cast<uint32_t*>( - mSDLSurface->pixels))[i]; - c &= ~fmt->Amask; - c |= ((a >> fmt->Aloss) << fmt->Ashift & fmt->Amask); - (static_cast<uint32_t*>(mSDLSurface->pixels))[i] = c; + const uint8_t sourceAlpha = mAlphaChannel[i]; + if (sourceAlpha > 0) + { + const uint8_t a = static_cast<uint8_t>( + static_cast<float>(sourceAlpha) * mAlpha); + + uint32_t c = (static_cast<uint32_t*>( + mSDLSurface->pixels))[i]; + c &= invMask; + c |= ((a >> aloss) << ashift & amask); + (static_cast<uint32_t*>(mSDLSurface->pixels))[i] = c; + } + } + } + else + { + for (int y = by; y < maxHeight; y ++) + { + const int idx = y * sw; + const int x1 = idx + bx; + const int x2 = idx + maxWidth; + for (int i = x1; i < x2; i ++) + { + const uint8_t sourceAlpha = mAlphaChannel[i]; + if (sourceAlpha > 0) + { + const uint8_t a = static_cast<uint8_t>( + static_cast<float>(sourceAlpha) * mAlpha); + + uint32_t c = (static_cast<uint32_t*>( + mSDLSurface->pixels))[i]; + c &= invMask; + c |= ((a >> aloss) << ashift & amask); + (static_cast<uint32_t*>( + mSDLSurface->pixels))[i] = c; + } + } } } |