diff options
author | Marcus Comstedt | 2014-01-10 20:02:24 +0100 |
---|---|---|
committer | Marcus Comstedt | 2014-01-10 20:04:10 +0100 |
commit | 4b81b1299da2d81bf457b245b1f8cb3d21c8172f (patch) | |
tree | 22e3ef43a9a8b6ea21d90949dd04e6d759557389 | |
parent | 51d7405a7b741b8028b83e1548b3b8260230c5a1 (diff) | |
download | scummvm-rg350-4b81b1299da2d81bf457b245b1f8cb3d21c8172f.tar.gz scummvm-rg350-4b81b1299da2d81bf457b245b1f8cb3d21c8172f.tar.bz2 scummvm-rg350-4b81b1299da2d81bf457b245b1f8cb3d21c8172f.zip |
GRAPHICS: Fix dest alpha formula in blendPixelPtr
The original alpha computation formula had a problem: If something was
drawn on top of a pixel that was already fully opaque, there would be
an overflow in the computed alpha, and the destination alpha would be
truncated to 0 (fully transparent).
In commit 264ba4a9 this formula was replaced with another one, which
did not have overflows but also was not correct.
This commits introduces a new formula, where the rounding errors have
been turned in another direction; drawing a fully opaque pixel on top
of a transparent one would result in a pixel which is almost, but not
fully, opaque. However, this is no problem in practice, since drawing
fully opaque pixels can be achieved with much less code as a special
case, so add that (also improves rendering speed).
-rw-r--r-- | graphics/VectorRendererSpec.cpp | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp index de249e8711..a3ec66a29d 100644 --- a/graphics/VectorRendererSpec.cpp +++ b/graphics/VectorRendererSpec.cpp @@ -620,7 +620,10 @@ applyScreenShading(GUI::ThemeEngine::ShadingStyle shadingStyle) { template<typename PixelType> inline void VectorRendererSpec<PixelType>:: blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha) { - if (sizeof(PixelType) == 4) { + if (alpha == 0xff) { + // fully opaque pixel, don't blend + *ptr = color | _alphaMask; + } else if (sizeof(PixelType) == 4) { const byte sR = (color & _redMask) >> _format.rShift; const byte sG = (color & _greenMask) >> _format.gShift; const byte sB = (color & _blueMask) >> _format.bShift; @@ -628,15 +631,17 @@ blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha) { byte dR = (*ptr & _redMask) >> _format.rShift; byte dG = (*ptr & _greenMask) >> _format.gShift; byte dB = (*ptr & _blueMask) >> _format.bShift; + byte dA = (*ptr & _alphaMask) >> _format.aShift; dR += ((sR - dR) * alpha) >> 8; dG += ((sG - dG) * alpha) >> 8; dB += ((sB - dB) * alpha) >> 8; + dA += ((0xff - dA) * alpha) >> 8; *ptr = ((dR << _format.rShift) & _redMask) | ((dG << _format.gShift) & _greenMask) | ((dB << _format.bShift) & _blueMask) - | (*ptr & _alphaMask); + | ((dA << _format.aShift) & _alphaMask); } else if (sizeof(PixelType) == 2) { int idst = *ptr; int isrc = color; @@ -651,7 +656,9 @@ blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha) { (_blueMask & ((idst & _blueMask) + ((int)(((int)(isrc & _blueMask) - (int)(idst & _blueMask)) * alpha) >> 8))) | - (idst & _alphaMask)); + (_alphaMask & ((idst & _alphaMask) + + ((int)(((int)(_alphaMask) - + (int)(idst & _alphaMask)) * alpha) >> 8)))); } else { error("Unsupported BPP format: %u", (uint)sizeof(PixelType)); } |