Closed Bug 2055747 Opened 1 month ago Closed 1 month ago

Masked absolutely positioned child renders with a 1px gap at some zoom levels

Categories

(Core :: Web Painting, defect)

Firefox 154
defect

Tracking

()

RESOLVED FIXED
155 Branch
Tracking Status
firefox-esr140 --- unaffected
firefox152 --- unaffected
firefox153 --- disabled
firefox154 --- wontfix
firefox155 --- fixed

People

(Reporter: betauploader3, Assigned: gw)

References

(Regression)

Details

(Keywords: regression)

Attachments

(3 files)

User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:152.0) Gecko/20100101 Firefox/152.0

Steps to reproduce:

User Agent:
Firefox Nightly 154

Expected Results:
The masked child element should render at its specified position.

When an absolutely positioned child is placed exactly at the bottom edge of its parent, no gap should appear between the two elements.

Actual Results:
In current Firefox Nightly builds, a 1px gap can appear between the parent and the masked absolutely positioned child at certain page zoom levels.

The child is positioned with top equal to the parent's height, so it should start exactly at the parent's bottom edge. However, when the child has a CSS mask and contains inline text, its painted output can appear 1px lower than expected, exposing the page background between the two elements.

Removing the CSS mask eliminates the gap. Setting an explicit line-height on the child also eliminates the gap.

This does not reproduce in Firefox 152 release or Firefox 153 beta, so it appears to be a recent regression.

Steps to Reproduce:

  1. Create a new, clean Firefox profile.
  2. Set layout.css.devPixelsPerPx to 1.
  3. Open the attached reduced test case.
  4. Zoom the page in and out.

Observed behavior:
At certain zoom levels, a 1px gap appears between the parent and the masked child. The gap disappears at other zoom levels.

Reproducible zoom levels with layout.css.devPixelsPerPx = 1:
110%
120%
125%
133%
150%
170%

With other layout.css.devPixelsPerPx values, the issue appears at different zoom levels. The exact affected zoom levels depend on the combination of browser scaling and page zoom.

Additional Notes:

  • The issue reproduces on a clean profile using the attached reduced test case.
  • Firefox 152 release and Firefox 153 beta do not exhibit this behavior.
  • Removing the mask or setting an explicit line-height on the child avoids the issue.
  • This seems related to rendering, clipping, or pixel snapping of masked absolutely positioned content with inline text under scaling.
  • This may affect websites and browser UI components that align masked or custom-shaped child elements with adjacent surfaces.

The Bugbug bot thinks this bug should belong to the 'Core::CSS Parsing and Computation' component, but is not confident enough to move the bug to that component.

Component: Untriaged → General
Regressed by: 1973192
Component: General → Web Painting
Product: Firefox → Core
Status: UNCONFIRMED → NEW
Ever confirmed: true

:hiro, since you are the author of the regressor, bug 2048146, could you take a look? Also, could you set the severity field?

For more information, please visit BugBot documentation.

Flags: needinfo?(hikezoe.birchill)

Thank you, Alice!

Flags: needinfo?(hikezoe.birchill) → needinfo?(mozilla)

The mask alpha blob is rasterized on the nearest-pixel grid at itemRect ==
round(bounds); WebRender maps it onto the mask clip node's rect and snaps that
rect to device pixels at frame time.

Since bug 1973192, with pixel alignment disabled, imageRect was
bounds.Intersect(GetBuildingRect()). The building rect is the border-box paint
rect, which can exclude a partially-covered edge row that the blob did
rasterize (the visual-overflow row of an abs-positioned masked child). Cropping
to it there, then snapping independently at a fractional device position, landed
the mask ~1px below its alpha and clipped the child's top row -- a 1px gap.

Send the unrounded bounds (so WebRender still snaps in lockstep with the masked
content), clamped to the union of the building rect and visibleRect. visibleRect
is the rasterized region on the blob's grid, so the union keeps edge rows the
blob covers (fixing this bug) while still clamping away inflated bounds that were
never drawn into the blob -- e.g. a filter's blur region above the viewport,
which a plain full-bounds placement would wrongly include and which regressed
svg/filters/filter-clipped-rect-01.

Assignee: nobody → mozilla
Status: NEW → ASSIGNED
Flags: needinfo?(mozilla)
Pushed by gwatson@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/583ad225e6ec https://hg.mozilla.org/integration/autoland/rev/c826b2873e62 Clamp the WebRender mask placement rect to the region the blob covers. r=gfx-reviewers,nical
Regressions: 2056494
Status: ASSIGNED → RESOLVED
Closed: 1 month ago
Resolution: --- → FIXED
Target Milestone: --- → 155 Branch

The patch landed in nightly and beta is affected.
:gw, is this bug important enough to require an uplift?

For more information, please visit BugBot documentation.

Flags: needinfo?(mozilla)

I believe this should only occur in nightly (since disable pixel alignment is currently nightly only).

Flags: needinfo?(mozilla)
QA Whiteboard: [qa-triage-done-c156/b155]
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: