tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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:
Mlayout/reftests/forms/input/radio/reftest.list | 4++--
Mwidget/Theme.cpp | 39+++++++++++++++++++++------------------
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)) {