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

bluegr noreply at scummvm.org
Wed Sep 9 06:25:09 UTC 2026


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

Summary:
f2d3dbd3ee GUI: Don't restore a widget's shadow over its neighbour


Commit: f2d3dbd3ee157209aa96fcfb102a1cf0715bfadc
    https://github.com/scummvm/scummvm/commit/f2d3dbd3ee157209aa96fcfb102a1cf0715bfadc
Author: Miro Kropacek (miro.kropacek at gmail.com)
Date: 2026-09-09T09:25:05+03:00

Commit Message:
GUI: Don't restore a widget's shadow over its neighbour

In the grid launcher the disabled Remove Game button has a dark red line
one pixel wide down its left edge.

Widgets in a row sit two pixels apart, while a widget paints one pixel
past its rectangle and casts its shadow two pixels beyond that, so the
last pixel it paints lands on the widget to its right.

6fff1690a55 made this visible but it's not a regression. Before it, the
grey went into the back buffer, so the stolen pixel was grey-on-grey and
invisible; after it, the grey is painted on the screen afterwards and
the stolen pixel comes back from the back buffer as red.

Restoring everything a widget can paint into is more than it needs. The
restore is there to wipe off the hovered or disabled state, so it only
needs to reach as far as those states are drawn. Neither of them casts a
shadow on the drop-down button, so its restore now stops at the button
and leaves the neighbour alone.

Changed paths:
    gui/ThemeEngine.cpp
    gui/ThemeEngine.h


diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp
index 8132caa937f..d0ebc68e1c2 100644
--- a/gui/ThemeEngine.cpp
+++ b/gui/ThemeEngine.cpp
@@ -83,6 +83,10 @@ struct WidgetDrawData {
 	uint16 _backgroundOffset;
 	uint16 _shadowOffset;
 
+	/** Extra space occupied by the items drawn on top of this one */
+	uint16 _restoreOffset;    ///< To the left and to the top
+	uint16 _restoreEndOffset; ///< To the right and to the bottom
+
 	DrawLayer _layer;
 
 
@@ -759,9 +763,26 @@ void ThemeEngine::loadTheme(const Common::String &themeId) {
 			warning("Missing data asset: '%s' in theme '%s", kDrawDataDefaults[i].name, themeId.c_str());
 		} else {
 			_widgets[i]->calcBackgroundOffset();
+			_widgets[i]->_restoreOffset = _widgets[i]->_restoreEndOffset = 0;
 		}
 	}
 
+	// A draw data item only ever has to restore what the items drawn on top of
+	// it can have covered
+	for (int i = 0; i < kDrawDataMAX; ++i) {
+		DrawData parentType = kDrawDataDefaults[i].parent;
+
+		if (parentType == kDDNone || parentType == i || !_widgets[i] || !_widgets[parentType])
+			continue;
+
+		const WidgetDrawData *child = _widgets[i];
+		WidgetDrawData *parent = _widgets[parentType];
+
+		parent->_restoreOffset = MAX(parent->_restoreOffset, child->_backgroundOffset);
+		parent->_restoreEndOffset = MAX<uint16>(parent->_restoreEndOffset,
+		                                        child->_backgroundOffset + 1 + child->_shadowOffset);
+	}
+
 	debug(6, "Finished loading theme %s", themeId.c_str());
 }
 
@@ -918,6 +939,24 @@ Common::Rect ThemeEngine::getDrawDataExtendedRect(DrawData type, const Common::R
 	return extendedRect;
 }
 
+Common::Rect ThemeEngine::getDrawDataRestoreRect(DrawData type, const Common::Rect &r) const {
+	WidgetDrawData *drawData = _widgets[type];
+	if (!drawData)
+		return Common::Rect();
+
+	Common::Rect restoreRect = r;
+	restoreRect.clip(_screen.w, _screen.h);
+
+	// The item's own edge and shadow reach further out, onto pixels that belong
+	// to the neighbouring widgets and must not be restored over what they drew
+	restoreRect.left -= drawData->_restoreOffset;
+	restoreRect.top -= drawData->_restoreOffset;
+	restoreRect.right += drawData->_restoreEndOffset;
+	restoreRect.bottom += drawData->_restoreEndOffset;
+
+	return restoreRect;
+}
+
 void ThemeEngine::drawDD(DrawData type, const Common::Rect &r, uint32 dynamic, bool forceRestore) {
 	WidgetDrawData *drawData = _widgets[type];
 
@@ -945,8 +984,14 @@ void ThemeEngine::drawDD(DrawData type, const Common::Rect &r, uint32 dynamic, b
 		return;
 	}
 
-	if (forceRestore || drawData->_layer == kDrawLayerBackground)
-		restoreBackground(extendedRect);
+	if (forceRestore || drawData->_layer == kDrawLayerBackground) {
+		// Clearing the background wipes everything the widget draws into, a
+		// plain redraw only what the items drawn on top of it can have covered
+		Common::Rect restoreRect = forceRestore ? extendedRect : getDrawDataRestoreRect(type, r);
+		restoreRect.clip(_clip);
+
+		restoreBackground(restoreRect);
+	}
 
 	if (drawData->_layer == _layerToDraw) {
 		Common::List<Graphics::DrawStep>::const_iterator step;
diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h
index f3dc23c7da0..63fbb14cd75 100644
--- a/gui/ThemeEngine.h
+++ b/gui/ThemeEngine.h
@@ -757,6 +757,13 @@ protected:
 	 */
 	Common::Rect getDrawDataExtendedRect(DrawData type, const Common::Rect &r) const;
 
+	/**
+	 * Compute the rectangle to restore from the backbuffer for a given draw data
+	 * type applied to the given base rect. Covers the item and the ones drawn on
+	 * top of it, but not its own edge and shadow.
+	 */
+	Common::Rect getDrawDataRestoreRect(DrawData type, const Common::Rect &r) const;
+
 	/**
 	 * DEBUG: Draws a white square and writes some text next to it.
 	 */




More information about the Scummvm-git-logs mailing list