Bug 244966 - [LBSE] Outermost <svg> elements are not device-pixel aligned
Summary: [LBSE] Outermost <svg> elements are not device-pixel aligned
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: SVG (show other bugs)
Version: WebKit Local Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Nikolas Zimmermann
URL:
Keywords: InRadar
Depends on:
Blocks: 90738
  Show dependency treegraph
 
Reported: 2022-09-09 03:34 PDT by Nikolas Zimmermann
Modified: 2022-09-16 08:47 PDT (History)
4 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Nikolas Zimmermann 2022-09-09 03:34:31 PDT
Whenever a SVG document fragment is placed in an enclosing HTML/CSS context, it receives its position per CSS rules (depending on 'display', 'position', etc.).
These are potentially sub-pixel positions, such as x=8, y=79.8456.

For HTML/CSS renderers the final position (in local coordinates) is pixel snapped, to enforce device-pixel alignment (no off-device-pixel painting).
In WebCore "adjustedPaintOffset" (== paintOffset [external] + location() [intrinsic]) is the quantity that's pixel snapped within the Render*::paint() methods.

The SVG render tree does not pixel snap any coordinates/lengths, except for the outermost <svg> renderer. There should be no visual difference between a HTML
document drawing a box with a green background, and an equivalent SVG document that does the same using a <rect> element. Therefore the legacy SVG engine always
rounded the 'adjustedPaintOffset' to the nearest integer, simulating the effect in the HTML/CSS rendering tree (not correct in all deviceScaleFactor configurations though!).

In LBSE, pixel-snapping or rounding the 'adjustedPaintOffset' in RenderSVGRoot won't have the same affect as in the legacy engine: LBSE uses self-painting layers
to paint the SVG document -- therefore any transformation needs to be applied on layer-level to affect the descendant renderers (that themselves use self-painting layers!).

RenderLayer::paintLayerByApplingTransform() already contains all the code necessary to place outer <svg> elements on device-pixel aligned boundaries. The subpixelOffset
is applied as transformation once for the outermost <svg>, and ignored (set to zero) for any other descendant SVG renderer. Pixel snapping is only relevant from RenderView
downwards to the (and including) RenderSVGRoot -- the rest of the SVG subtree is not using pixel snapping / device pixel alignment.

This will allow us to enable testing the few hundred tests in svg/dynamic-updates, that are currently skipped in LBSE (because they all fail).
All of them showed subtle rendering differences caused by the currently _missing_ device pixel alignment for RenderSVGRoot.
Comment 1 Nikolas Zimmermann 2022-09-09 03:56:55 PDT
Pull request: https://github.com/WebKit/WebKit/pull/4158
Comment 2 Radar WebKit Bug Importer 2022-09-16 03:35:17 PDT
<rdar://problem/100019924>
Comment 3 EWS 2022-09-16 08:47:03 PDT
Committed 254558@main (de2323d7e2c8): <https://commits.webkit.org/254558@main>

Reviewed commits have been landed. Closing PR #4158 and removing active labels.