Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: 3adec8e64df0536e4d34c37902714552fbc0057d
      
https://github.com/WebKit/WebKit/commit/3adec8e64df0536e4d34c37902714552fbc0057d
  Author: Ahmad Saleem <[email protected]>
  Date:   2026-08-15 (Sat, 15 Aug 2026)

  Changed paths:
    M LayoutTests/fast/borders/hidpi-outline-hairline-painting-expected.html
    A LayoutTests/fast/css/outline-offset-used-value-zoom-rounding-expected.txt
    A LayoutTests/fast/css/outline-offset-used-value-zoom-rounding.html
    M 
LayoutTests/imported/w3c/web-platform-tests/css/css-borders/outline-offset-rounding.tentative-expected.txt
    M 
LayoutTests/imported/w3c/web-platform-tests/css/css-borders/outline-offset-rounding.tentative.html
    A 
LayoutTests/imported/w3c/web-platform-tests/css/css-ui/animation/outline-offset-interpolation-rounding.tentative-expected.txt
    A
LayoutTests/imported/w3c/web-platform-tests/css/css-ui/animation/outline-offset-interpolation-rounding.tentative.html
    M Source/WebCore/Headers.cmake
    M Source/WebCore/Sources.txt
    M Source/WebCore/WebCore.xcodeproj/project.pbxproj
    M Source/WebCore/accessibility/AccessibilityRenderObject.cpp
    M Source/WebCore/rendering/OutlinePainter.cpp
    M Source/WebCore/rendering/RenderElement.cpp
    M Source/WebCore/rendering/cocoa/RenderThemeCocoa.mm
    M Source/WebCore/style/computed/StyleComputedStyle.cpp
    M Source/WebCore/style/computed/StyleComputedStyle.h
    M Source/WebCore/style/computed/StyleComputedStyleBase.h
    M Source/WebCore/style/values/backgrounds/StyleLineWidth.cpp
    M Source/WebCore/style/values/backgrounds/StyleLineWidth.h
    A Source/WebCore/style/values/outline/StyleOutlineOffset.cpp
    M Source/WebCore/style/values/outline/StyleOutlineOffset.h
    A Source/WebCore/style/values/primitives/StyleSnapLengthAsBorderWidth.cpp
    A
Source/WebCore/style/values/primitives/StyleSnapLengthAsBorderWidth.h
    M Source/WebCore/testing/Internals.cpp

  Log Message:
  -----------
  [css-ui] outline-offset computed value should be snapped as a line width
https://bugs.webkit.org/show_bug.cgi?id=317427
rdar://180054053

Reviewed by Sam Weinig and Darin Adler.

This patch aligns WebKit with Gecko / Firefox and Blink / Chromium.

The CSSWG resolved that `outline-offset` should be snapped to an integer number 
of
device pixels the same way `outline-width` and `border-width` are
(w3c/csswg-drafts#12906). WebKit used the raw, unsnapped length, so
getComputedStyle().outlineOffset returned values like "0.1px" instead of "1px".

Move "snap a length as a border width"
(https://drafts.csswg.org/css-values-4/#snap-a-length-as-a-border-width) out of
`LineWidth` into its own file, exposing the `float` overload directly and adding
signed overloads for lengths that may be negative, which snap the magnitude
and
restore the sign: zero is unchanged, a magnitude below 1 device pixel rounds 
away
from zero, a larger magnitude rounds toward zero.

`outline-offset` now snaps in the same three places `outline-width` does:

 - `CSSValueConversion<OutlineOffset>` snaps the computed value.
 - `Blending<OutlineOffset>` re-snaps blended values, keeping animations on 
device
   pixels. It also has to supply `canBlend()`, since a full specialization 
replaces
   the generic `ValueOrKeyword` one, which is what makes `inset` interpolate
   discretely against a length rather than blending as an empty value.
 - `Evaluation<UsedOutlineOffset>` re-snaps after zoom is applied, keeping the 
used
   value on device pixels at any page zoom. `ComputedStyle::usedOutlineOffset()`
   returns `Style::UsedOutlineOffset` so that evaluating it requires a device 
scale
   factor, and its callers pass one.

The manual `floorToDevicePixel()` in RenderThemeCocoa is subsumed by that 
used-value
snapping. It is
not quite equivalent: for a magnitude below one device pixel, `floor`
gave 0 while snapping rounds away from zero to 1 device pixel, so an iOS focus 
ring
at a zoom below 1 now scales by the offset instead of ignoring it. That is the
behavior `outline-width` already has.

`inset` resolves to the negated used `outline-width`, and snapping both after 
zoom
makes them cancel exactly, which they previously did not at fractional zoom.

* LayoutTests/fast/borders/hidpi-outline-hairline-painting-expected.html: 
Rebaselined.
This reference was authored against unsnapped offsets, and at the 2x device 
scale factor
this test runs at, snapping the offset changes the painted outline geometry.
* LayoutTests/fast/css/outline-offset-used-value-zoom-rounding-expected.txt: 
Added.
* LayoutTests/fast/css/outline-offset-used-value-zoom-rounding.html: Added. 
Covers the
used value after zoom, which needs `internals` since it is not web-exposed.
*
LayoutTests/imported/w3c/web-platform-tests/css/css-borders/outline-offset-rounding.tentative.html:
The test as imported hard-codes expectations that assume 1 device pixel is 1 
CSS pixel, so its
sub-pixel sub-tests reported FAIL at any other device scale factor even though 
the engine was
behaving as specified. Derive the expectations from window.devicePixelRatio 
instead, and add
sub-tests that cross-check outline-offset against outline-width for the same 
input, which is a
direct statement of the CSSWG resolution and holds at any device scale factor. 
Verified all 30
sub-tests pass at 1x, 2x and 3x. To be upstreamed.
* 
LayoutTests/imported/w3c/web-platform-tests/css/css-borders/outline-offset-rounding.tentative-expected.txt:
 Progression
* 
LayoutTests/imported/w3c/web-platform-tests/css/css-ui/animation/outline-offset-interpolation-rounding.tentative-expected.txt:
 Added.
*
LayoutTests/imported/w3c/web-platform-tests/css/css-ui/animation/outline-offset-interpolation-rounding.tentative.html:
 Added.
Covers snapping of blended values, deriving expectations from 
window.devicePixelRatio so they hold
at any device scale factor. The `inset` sub-test is gated on CSS.supports(), 
since Chromium and
Gecko do not implement it yet and drop the keyframe. To be upstreamed.
* Source/WebCore/Headers.cmake:
* Source/WebCore/Sources.txt:
* Source/WebCore/WebCore.xcodeproj/project.pbxproj:
* Source/WebCore/accessibility/AccessibilityRenderObject.cpp:
(WebCore::AccessibilityRenderObject::elementPath const):
* Source/WebCore/rendering/OutlinePainter.cpp:
(WebCore::OutlinePainter::paintOutline const):
(WebCore::OutlinePainter::paintOutlineWithLineRects const):
(WebCore::OutlinePainter::paintFocusRing const):
* Source/WebCore/rendering/RenderElement.cpp:
(WebCore::RenderElement::repaintAfterLayoutIfNeeded):
*
Source/WebCore/rendering/cocoa/RenderThemeCocoa.mm:
(WebCore::drawFocusRingForPathForVectorBasedControls):
* Source/WebCore/style/computed/StyleComputedStyle.cpp:
(WebCore::Style::ComputedStyle::usedOutlineOffset const):
(WebCore::Style::ComputedStyle::usedOutlineSize const):
* Source/WebCore/style/computed/StyleComputedStyle.h:
* Source/WebCore/style/computed/StyleComputedStyleBase.h:
* Source/WebCore/style/values/backgrounds/StyleLineWidth.cpp:
(WebCore::Style::snapLengthAsBorderWidth): Deleted.
(WebCore::Style::LineWidth::snapLengthAsBorderWidth): Deleted.
* Source/WebCore/style/values/backgrounds/StyleLineWidth.h:
* Source/WebCore/style/values/outline/StyleOutlineOffset.cpp:
(WebCore::Style::CSSValueConversion<OutlineOffset>::operator()):
(WebCore::Style::Blending<OutlineOffset>::canBlend):
(WebCore::Style::Blending<OutlineOffset>::blend):
(WebCore::Style::Evaluation<UsedOutlineOffset, float>::operator()):
(WebCore::Style::Evaluation<UsedOutlineOffset,
LayoutUnit>::operator()):
* Source/WebCore/style/values/outline/StyleOutlineOffset.h:
* Source/WebCore/style/values/primitives/StyleSnapLengthAsBorderWidth.cpp: 
Added.
(WebCore::Style::snapLengthAsBorderWidth):
(WebCore::Style::snapSignedLengthAsBorderWidth):
* Source/WebCore/style/values/primitives/StyleSnapLengthAsBorderWidth.h: Added.
* Source/WebCore/testing/Internals.cpp:
(WebCore::Internals::usedOutlineOffset):

Canonical link: 
https://flagged.apple.com:443/proxy?t2=Dh3n1i1Fv9&o=aHR0cHM6Ly9jb21taXRzLndlYmtpdC5vcmcvMzE5MjM2QG1haW4=&emid=ff31d39f-26a4-4a58-9746-489113a7a11e&c=11



To unsubscribe from these emails, change your notification settings at 
https://github.com/WebKit/WebKit/settings/notifications

Reply via email to