[Scummvm-git-logs] scummvm master -> f12813c630929a2080307fb0afa51bd38d94cca0

criezy criezy at scummvm.org
Mon Feb 22 22:59:10 UTC 2021


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
f12813c630 GRAPHICS: Support having transparent ManagedSurface


Commit: f12813c630929a2080307fb0afa51bd38d94cca0
    https://github.com/scummvm/scummvm/commit/f12813c630929a2080307fb0afa51bd38d94cca0
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2021-02-22T22:59:07Z

Commit Message:
GRAPHICS: Support having transparent ManagedSurface

Changed paths:
    graphics/managed_surface.cpp
    graphics/managed_surface.h


diff --git a/graphics/managed_surface.cpp b/graphics/managed_surface.cpp
index 8d088f8da8..dc1b1b1b4f 100644
--- a/graphics/managed_surface.cpp
+++ b/graphics/managed_surface.cpp
@@ -251,8 +251,7 @@ void ManagedSurface::blitFromInner(const Surface &src, const Common::Rect &srcRe
 
 	uint destPixel;
 	byte rSrc, gSrc, bSrc, aSrc;
-	byte rDest = 0, gDest = 0, bDest = 0;
-	double alpha;
+	byte aDest = 0, rDest = 0, gDest = 0, bDest = 0;
 
 	if (!srcRect.isValidRect())
 		return;
@@ -272,68 +271,82 @@ void ManagedSurface::blitFromInner(const Surface &src, const Common::Rect &srcRe
 		const byte *srcP = (const byte *)src.getBasePtr(srcRect.left, scaleYCtr / SCALE_THRESHOLD + srcRect.top);
 		byte *destP = (byte *)getBasePtr(destRect.left, destY);
 
-		if (src.format == format && noScale) {
-			// Matching surface formats, so we can do a straight copy
+		// For paletted format, assume the palette is the same and there is no transparency.
+		// We can thus do a straight copy of the pixels.
+		if (format.bytesPerPixel == 1 && noScale) {
 			Common::copy(srcP, srcP + srcRect.width() * format.bytesPerPixel, destP);
-		} else {
-			// Loop through drawing the pixels of the row
-			for (int destX = destRect.left, xCtr = 0, scaleXCtr = 0; destX < destRect.right; ++destX, ++xCtr, scaleXCtr += scaleX) {
-				if (destX < 0 || destX >= w)
-					continue;
+			continue;
+		}
 
-				const byte *srcVal = &srcP[scaleXCtr / SCALE_THRESHOLD * src.format.bytesPerPixel];
-				byte *destVal = &destP[xCtr * format.bytesPerPixel];
-				if (src.format == format) {
-					if (format.bytesPerPixel == 1)
-						*destVal = *srcVal;
-					else if (format.bytesPerPixel == 2)
-						*(uint16 *)destVal = *(const uint16*)srcVal;
-					else
-						*(uint32 *)destVal = *(const uint32*)srcVal;
-					continue;
-				}
+		// Loop through drawing the pixels of the row
+		for (int destX = destRect.left, xCtr = 0, scaleXCtr = 0; destX < destRect.right; ++destX, ++xCtr, scaleXCtr += scaleX) {
+			if (destX < 0 || destX >= w)
+				continue;
 
-				if (src.format.bytesPerPixel == 1) {
-					assert(srcPalette != nullptr);	// Catch the cases when palette is missing
-					// Get the palette color
-					const uint32 col = srcPalette[*srcVal];
-					rSrc = col & 0xff;
-					gSrc = (col >> 8) & 0xff;
-					bSrc = (col >> 16) & 0xff;
-					aSrc = (col >> 24) & 0xff;
-				} else {
-					// Use the src's pixel format to split up the source pixel
-					src.format.colorToARGB(src.format.bytesPerPixel == 2
-						? *(const uint16 *)srcVal : *(const uint32 *)srcVal,
-						aSrc, rSrc, gSrc, bSrc);
-				}
+			const byte *srcVal = &srcP[scaleXCtr / SCALE_THRESHOLD * src.format.bytesPerPixel];
+			byte *destVal = &destP[xCtr * format.bytesPerPixel];
+			if (format.bytesPerPixel == 1) {
+				*destVal = *srcVal;
+				continue;
+			}
 
-				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;
+			if (src.format.bytesPerPixel == 1) {
+				assert(srcPalette != nullptr);	// Catch the cases when palette is missing
+				// Get the palette color
+				const uint32 col = srcPalette[*srcVal];
+				rSrc = col & 0xff;
+				gSrc = (col >> 8) & 0xff;
+				bSrc = (col >> 16) & 0xff;
+				aSrc = (col >> 24) & 0xff;
+			} else {
+				// Use the src's pixel format to split up the source pixel
+				src.format.colorToARGB(src.format.bytesPerPixel == 2
+					? *(const uint16 *)srcVal : *(const uint32 *)srcVal,
+					aSrc, rSrc, gSrc, bSrc);
+			}
+
+			if (aSrc == 0) {
+				// Completely transparent, so skip
+				continue;
+			} else if (aSrc == 0xff) {
+				// Completely opaque, so copy RGB values over
+				aDest = aSrc;
+				rDest = rSrc;
+				gDest = gSrc;
+				bDest = bSrc;
+			} else {
+				// Partially transparent, so calculate new pixel colors
+				if (format.bytesPerPixel == 2) {
+					uint32 destColor = *(uint16 *)destVal;
+					format.colorToARGB(destColor, aDest, rDest, gDest, bDest);
+				} else if (format.bytesPerPixel == 4) {
+					uint32 destColor = *(uint32 *)destVal;
+					format.colorToARGB(destColor, aDest, rDest, gDest, bDest);
 				} else {
-					// Partially transparent, so calculate new pixel colors
-					alpha = (double)aSrc / 255.0;
-					rDest = static_cast<byte>((rSrc * alpha) + (rDest * (1.0 - alpha)));
-					gDest = static_cast<byte>((gSrc * alpha) + (gDest * (1.0 - alpha)));
-					bDest = static_cast<byte>((bSrc * alpha) + (bDest * (1.0 - alpha)));
+					aDest = 0xFF;
+					rDest = destVal[0];
+					gDest = destVal[1];
+					bDest = destVal[2];
 				}
 
-				destPixel = format.ARGBToColor(0xff, rDest, gDest, bDest);
-				if (format.bytesPerPixel == 2)
-					*(uint16 *)destVal = destPixel;
-				else if (format.bytesPerPixel == 4)
-					*(uint32 *)destVal = destPixel;
-				else {
-					destVal[0] = rDest;
-					destVal[1] = gDest;
-					destVal[2] = bDest;
-				}
+				double sAlpha = (double)aSrc / 255.0;
+				double dAlpha = (double)aDest / 255.0;
+				dAlpha *= (1.0 - sAlpha);
+				rDest = static_cast<uint8>((rSrc * sAlpha + rDest * dAlpha) / (sAlpha + dAlpha));
+				gDest = static_cast<uint8>((gSrc * sAlpha + gDest * dAlpha) / (sAlpha + dAlpha));
+				bDest = static_cast<uint8>((bSrc * sAlpha + bDest * dAlpha) / (sAlpha + dAlpha));
+				aDest = static_cast<uint8>(255. * (sAlpha + dAlpha));
+			}
+
+			destPixel = format.ARGBToColor(aDest, rDest, gDest, bDest);
+			if (format.bytesPerPixel == 2)
+				*(uint16 *)destVal = destPixel;
+			else if (format.bytesPerPixel == 4)
+				*(uint32 *)destVal = destPixel;
+			else {
+				destVal[0] = rDest;
+				destVal[1] = gDest;
+				destVal[2] = bDest;
 			}
 		}
 	}
@@ -471,13 +484,11 @@ void transBlitPixel(TSRC srcVal, TDEST &destVal, const Graphics::PixelFormat &sr
 		srcFormat.colorToARGB(srcVal, aSrc, rSrc, gSrc, bSrc);
 	}
 
-	byte rDest, gDest, bDest;
-	destFormat.colorToRGB(destVal, rDest, gDest, bDest);
-
 	if (srcAlpha != 0xff) {
 		aSrc = aSrc * srcAlpha / 255;
 	}
 
+	byte aDest, rDest, gDest, bDest;
 	if (aSrc == 0) {
 		// Completely transparent, so skip
 		return;
@@ -486,15 +497,20 @@ void transBlitPixel(TSRC srcVal, TDEST &destVal, const Graphics::PixelFormat &sr
 		rDest = rSrc;
 		gDest = gSrc;
 		bDest = bSrc;
+		aDest = 0xff;
 	} else {
 		// Partially transparent, so calculate new pixel colors
-		double alpha = (double)aSrc / 255.0;
-		rDest = static_cast<byte>((rSrc * alpha) + (rDest * (1.0 - alpha)));
-		gDest = static_cast<byte>((gSrc * alpha) + (gDest * (1.0 - alpha)));
-		bDest = static_cast<byte>((bSrc * alpha) + (bDest * (1.0 - alpha)));
+		destFormat.colorToARGB(destVal, aDest, rDest, gDest, bDest);
+		double sAlpha = (double)aSrc / 255.0;
+		double dAlpha = (double)aDest / 255.0;
+		dAlpha *= (1.0 - sAlpha);
+		rDest = static_cast<uint8>((rSrc * sAlpha + rDest * dAlpha) / (sAlpha + dAlpha));
+		gDest = static_cast<uint8>((gSrc * sAlpha + gDest * dAlpha) / (sAlpha + dAlpha));
+		bDest = static_cast<uint8>((bSrc * sAlpha + bDest * dAlpha) / (sAlpha + dAlpha));
+		aDest = static_cast<uint8>(255. * (sAlpha + dAlpha));
 	}
 
-	destVal = destFormat.ARGBToColor(0xff, rDest, gDest, bDest);
+	destVal = destFormat.ARGBToColor(aDest, rDest, gDest, bDest);
 }
 
 template<>
@@ -642,18 +658,9 @@ void ManagedSurface::addDirtyRect(const Common::Rect &r) {
 	}
 }
 
-uint32 ManagedSurface::addAlphaToColor(uint32 color) {
-	if (format.aBits() == 0)
-		return color;
-
-	byte r, g, b;
-	format.colorToRGB(color, r, g, b);
-	return format.ARGBToColor(0xff, r, g, b);
-}
-
 void ManagedSurface::clear(uint color) {
 	if (!empty())
-		fillRect(getBounds(), addAlphaToColor(color));
+		fillRect(getBounds(), color);
 }
 
 void ManagedSurface::setPalette(const byte *colors, uint start, uint num) {
diff --git a/graphics/managed_surface.h b/graphics/managed_surface.h
index 531e4ba26b..80ef2c5669 100644
--- a/graphics/managed_surface.h
+++ b/graphics/managed_surface.h
@@ -91,12 +91,6 @@ protected:
 	 */
 	virtual void addDirtyRect(const Common::Rect &r);
 
-	/**
-	 * Adds a full solid alpha to the passed color for surfaces that have
-	 * an alpha channel
-	 */
-	uint32 addAlphaToColor(uint32 color);
-
 	/**
 	 * Inner method for blitting.
 	 */
@@ -513,7 +507,7 @@ public:
 	 * Draw a line.
 	 */
 	void drawLine(int x0, int y0, int x1, int y1, uint32 color) {
-		_innerSurface.drawLine(x0, y0, x1, y1, addAlphaToColor(color));
+		_innerSurface.drawLine(x0, y0, x1, y1, color);
 		addDirtyRect(Common::Rect(MIN(x0, x1), MIN(y0, y1), MAX(x0, x1), MAX(y0, y1)));
 	}
 
@@ -521,7 +515,7 @@ public:
 	 * Draw a thick line.
 	 */
 	void drawThickLine(int x0, int y0, int x1, int y1, int penX, int penY, uint32 color) {
-		_innerSurface.drawThickLine(x0, y0, x1, y1, penX, penY, addAlphaToColor(color));
+		_innerSurface.drawThickLine(x0, y0, x1, y1, penX, penY, color);
 		addDirtyRect(Common::Rect(MIN(x0, x1 + penX), MIN(y0, y1 + penY), MAX(x0, x1 + penX), MAX(y0, y1 + penY)));
 	}
 
@@ -529,7 +523,7 @@ public:
 	 * Draw a horizontal line.
 	 */
 	void hLine(int x, int y, int x2, uint32 color) {
-		_innerSurface.hLine(x, y, x2, addAlphaToColor(color));
+		_innerSurface.hLine(x, y, x2, color);
 		addDirtyRect(Common::Rect(x, y, x2 + 1, y + 1));
 	}
 
@@ -537,7 +531,7 @@ public:
 	 * Draw a vertical line.
 	 */
 	void vLine(int x, int y, int y2, uint32 color) {
-		_innerSurface.vLine(x, y, y2, addAlphaToColor(color));
+		_innerSurface.vLine(x, y, y2, color);
 		addDirtyRect(Common::Rect(x, y, x + 1, y2 + 1));
 	}
 
@@ -545,7 +539,7 @@ public:
 	 * Fill a rect with a given color.
 	 */
 	void fillRect(Common::Rect r, uint32 color) {
-		_innerSurface.fillRect(r, addAlphaToColor(color));
+		_innerSurface.fillRect(r, color);
 		addDirtyRect(r);
 	}
 
@@ -553,7 +547,7 @@ public:
 	 * Draw a frame around a specified rect.
 	 */
 	void frameRect(const Common::Rect &r, uint32 color) {
-		_innerSurface.frameRect(r, addAlphaToColor(color));
+		_innerSurface.frameRect(r, color);
 		addDirtyRect(r);
 	}
 




More information about the Scummvm-git-logs mailing list