commit ab84a7e4c545acc19e793568271cb02973e20980
parent ccae5969871d95771a3fad7d396661c741504ae5
Author: Emilio Cobos Álvarez <emilio@crisal.io>
Date: Fri, 31 Oct 2025 12:42:56 +0000
Bug 1993820 - Tweak checked radio rendering to minimize snapping artifacts. r=dholbert
We're drawing it as a background circle, and an inner background +
border circle, which means that the outer background can snap
differently.
Draw it as an outer background + border, and an inner circle instead, so
as to minimize snapping artifacts on the outer border.
Differential Revision: https://phabricator.services.mozilla.com/D270477
Diffstat:
2 files changed, 23 insertions(+), 20 deletions(-)
diff --git a/layout/reftests/forms/input/radio/reftest.list b/layout/reftests/forms/input/radio/reftest.list
@@ -4,6 +4,6 @@
== unchecked-appearance-none.html about:blank
!= checked-native.html about:blank
!= checked-native-notref.html about:blank
-fuzzy(0-2,0-16) == radio-clamp-01.html radio-clamp-01-ref.html # Rounded corner antialiasing
-fuzzy(0-2,0-16) skip-if(!gtkWidget) == radio-clamp-02.html radio-clamp-02-ref.html
+fuzzy(0-2,0-29) == radio-clamp-01.html radio-clamp-01-ref.html # Rounded corner antialiasing
+fuzzy(0-2,0-29) skip-if(!gtkWidget) == radio-clamp-02.html radio-clamp-02-ref.html
!= radio-minimum-size.html radio-minimum-size-notref.html
diff --git a/widget/Theme.cpp b/widget/Theme.cpp
@@ -633,26 +633,29 @@ void Theme::PaintRadioControl(PaintBackendData& aPaintData,
DPIRatio aDpiRatio) {
auto [backgroundColor, borderColor, checkColor] =
ComputeCheckboxColors(aState, StyleAppearance::Radio, aColors);
+ const bool isChecked = aState.HasState(ElementState::CHECKED);
{
- CSSCoord borderWidth = kCheckboxRadioBorderWidth;
- if (backgroundColor == borderColor) {
- borderWidth = 0.0f;
+ CSSCoord outerBorderWidth = kCheckboxRadioBorderWidth;
+ auto effectiveBackground = isChecked ? checkColor : backgroundColor;
+ if (effectiveBackground == borderColor) {
+ outerBorderWidth = 0.0f;
}
- PaintStrokedCircle(aPaintData, aRect, backgroundColor, borderColor,
- borderWidth, aDpiRatio);
- }
-
- if (aState.HasState(ElementState::CHECKED)) {
- // See bug 1951930 and bug 1941755 for some discussion on this chunk of
- // code.
- const CSSCoord kOuterBorderWidth = 1.0f;
- const CSSCoord kInnerBorderWidth = 2.0f;
- LayoutDeviceRect rect(aRect);
- auto width = LayoutDeviceCoord(
- ThemeDrawing::SnapBorderWidth(kOuterBorderWidth, aDpiRatio));
- rect.Deflate(width);
- PaintStrokedCircle(aPaintData, rect, backgroundColor, checkColor,
- kInnerBorderWidth, aDpiRatio);
+ PaintStrokedCircle(aPaintData, aRect, effectiveBackground, borderColor,
+ outerBorderWidth, aDpiRatio);
+ }
+
+ if (isChecked) {
+ // See bug 1951930 / bug 1941755 for discussion on this chunk of code.
+ constexpr CSSCoord kInnerBorderWidth = 2.0f;
+ LayoutDeviceRect innerCircleBounds(aRect);
+ // It's important that these are two different calls so that the snapping of
+ // the inner rect matches the one PaintStrokedCircle above does.
+ innerCircleBounds.Deflate(
+ ThemeDrawing::SnapBorderWidth(kCheckboxRadioBorderWidth, aDpiRatio));
+ innerCircleBounds.Deflate(
+ ThemeDrawing::SnapBorderWidth(kInnerBorderWidth, aDpiRatio));
+ PaintStrokedCircle(aPaintData, innerCircleBounds, backgroundColor,
+ sTransparent, 0.0f, aDpiRatio);
}
if (aState.HasState(ElementState::FOCUSRING)) {