diff options
Diffstat (limited to 'graphics')
| -rw-r--r-- | graphics/managed_surface.cpp | 49 | 
1 files changed, 47 insertions, 2 deletions
diff --git a/graphics/managed_surface.cpp b/graphics/managed_surface.cpp index 0b9fa11181..0b29b1937f 100644 --- a/graphics/managed_surface.cpp +++ b/graphics/managed_surface.cpp @@ -166,15 +166,60 @@ void ManagedSurface::blitFrom(const Surface &src, const Common::Rect &srcRect,  	Common::Rect srcBounds = srcRect;  	Common::Rect destBounds(destPos.x, destPos.y, destPos.x + srcRect.width(),  		destPos.y + srcRect.height()); -	assert(src.format.bytesPerPixel == format.bytesPerPixel); +	uint destPixel; +	byte rSrc, gSrc, bSrc, aSrc; +	byte rDest, gDest, bDest; +	double alpha;  	if (!srcRect.isValidRect() || !clip(srcBounds, destBounds))  		return; +	if (format != src.format) { +		// When the pixel format differs, both source an dest must be +		// 2 or 4 bytes per pixel +		assert(format.bytesPerPixel == 2 || format.bytesPerPixel == 4); +		assert(src.format.bytesPerPixel == 2 || src.format.bytesPerPixel == 4); +	} +  	for (int y = 0; y < srcBounds.height(); ++y) {  		const byte *srcP = (const byte *)src.getBasePtr(srcBounds.left, srcBounds.top + y);  		byte *destP = (byte *)getBasePtr(destBounds.left, destBounds.top + y); -		Common::copy(srcP, srcP + srcBounds.width() * format.bytesPerPixel, destP); + +		if (src.format == format && format.bytesPerPixel <= 2) { +			// Matching 8-bit or 16-bit surfaces (no alpha), so we can do a straight copy +			Common::copy(srcP, srcP + srcBounds.width() * format.bytesPerPixel, destP); +		} else { +			for (int x = 0; x < srcBounds.width(); ++x, +					srcP += src.format.bytesPerPixel, +					destP += format.bytesPerPixel) { +				src.format.colorToARGB(src.format.bytesPerPixel == 2 ? *(const uint16 *)srcP : *(const uint32 *)srcP, +					aSrc, rSrc, gSrc, bSrc); +				format.colorToRGB(format.bytesPerPixel == 2 ? *(const uint16 *)destP : *(const uint32 *)destP, +					rDest, gDest, bDest); + +				if (aSrc == 0) { +					// Completely transparent, so skip +					continue; +				} else if (aSrc == 0xff) { +					// Completely opaque, so copy RGB values over +					rDest = rSrc; +					gDest = gSrc; +					bDest = bSrc; +				} else { +					// Partially transparent, so calculate new pixel colors +					alpha = (double)aSrc / 255.0; +					rDest = (rSrc * alpha) + (rDest * (1.0 - alpha)); +					gDest = (gSrc * alpha) + (gDest * (1.0 - alpha)); +					bDest = (bSrc * alpha) + (bDest * (1.0 - alpha)); +				} + +				destPixel = format.ARGBToColor(0xff, rDest, gDest, bDest); +				if (format.bytesPerPixel == 2) +					*(uint16 *)destP = destPixel; +				else +					*(uint32 *)destP = destPixel; +			} +		}  	}  	addDirtyRect(Common::Rect(0, 0, this->w, this->h));  | 
