Closed gregwhitworth closed 5 years ago
Here is a demo page that clearly shows the issue:
https://output.jsbin.com/gemipizazi/1
If you load this in Chrome Canary with the --enable-use-zoom-for-dsf command-line flag (*), and resize the browser window vertically, there will be a number of visual artifacts in the rendering, that appear or disappear according to the different pixel snapping that happens with different viewport heights.
If you load the same demo in Safari Technical Preview with the experimental ResizeObserver turned on, and resize the browser vertically, you'll see the same kind of artifacts (but different ones, because the pixel snapping algorithm depends on the browser).
If you apply a hacked-up prototype of the device pixel border box observation feature to Chromium via patching this CL then the rendering artifacts are gone.
I tested these on a Retina MacBook Pro.
(*) This flag turns on pixel snapping at device pixel granularity, rather than CSS pixel granularity. This flag has already been shipped in Chrome on all platforms except for Mac, and will ship on Mac soon. It's also a necessary feature for high quality output, but orthogonal & complementary to the issue being discussed here.
I have added this issue to the agenda for next week's teleconference.
Another demo revision: https://jsbin.com/soqexor
The CSS Working Group just discussed device-pixel-border-box size
, and agreed to the following:
RESOLVED: Add API to get content box height and width in device pixel sizes to resize observer. Only return when requested and applies to all element.
So this will not be provided as a box option, but as a getter in the ResizeObserverEntry object?
If so, I see a problem with this when the scaling changes across multiple screens - The css pixel will stay the same, however, the device pixels will be different. This means that the resize observer will not fire, when it probably should?
It will be provided as a box option. The summary above didn't completely capture the discussion.
To summarize the conclusions from the meeting:
device-pixel-content-size
. (@fantasai pointed out that observing the border box was not what was desired. Also, @smfr pointed out that it doesn't need to be a rect, since the position is not useful.)devicePixelContentSize
, which will be populated if device-pixel-content-size
is being observed for the target element. If populated, it will contain a sequence of two longs, representing the width and height of the element, in device pixels.@chrishtr @atotic is this correct?
Yes. device-pixel-content-size will be an option, and the size will be reported on ResizeObserverEntry. Size could be defined as:
interface ResizeObserverSize {
readonly attribute unrestricted double inlineSize;
readonly attribute unrestricted double blockSize;
} ;
Side note: #3673 discussed how to handle fragments. Current resolution is that the sizes will be reported as an array. ResizeObserverEntry per spec would look like this:
{
target: Element
contentRect: {....}
devicePixelContentSize: [{ inlineSize: ..., blockSize: ... }]
}
Addressed by #4476
device-pixel-border-box size
device-pixel-border-box size is Element's border-box size in device pixels. It is always an integer, as there are no fractional device pixels. It can currently be approximated by
Math.round(borderBoxSize * window.devicePixelRatio)
, but it cannot be computed exactly, because native code uses a different rounding algorithm.Use case
This unusual size request comes from Chrome's WebGL canvas team. It solves the long standing WebGL developers problem: "How to create HiDPI canvas without moire pattern?".
The existing "best practice" for creating a HiDPI canvas is to set size of canvas context to a multiple of canvas's css width/height. Example:
The webgl context will be HiDPI, one one canvas pixel should correspond to one device pixel. But, because ctx.width is pixel snapped, ctx.width can differ from "true" device pixel width. This difference can cause visible moire patterns when rendered.
Because of this, WebGL team believes that web platform needs to provide an API for true device pixel width.
Discussion
This size has several interesting differences from others reported by ResizeObserver:
Q: Does this size belong to ResizeObserver, or should we create a diferent DOM API for it?
I can't think of a clean API that would provide same functionality. Web developers must observe this size, and respond to its changes. ResizeObserver is the only size-observing API. Observing border-box size, and providing "devicePixelSize()" method will not work, because devicePixelSize could change without border-box changing.
Q: Should we observe device-pixel-size on all elements, or just canvas?
Observing device-pixel-size comes with performance cost, because size must be checked when Element's position changes. For all other sizes, we do not need to check size when position changes. Weak preference: Only allow device-pixel-size observation for canvas.
Q: Should we report device-pixel-size on all elements, or just canvas?
Weak preference: make it canvas-only, because other elements cannot observe this size.
Originally posted by @atotic in https://github.com/w3c/csswg-drafts/issues/3326#issuecomment-440041374