Skip to content

Commit

Permalink
Add support for device-pixel-content-box-size w3c#3554 (w3c#4476)
Browse files Browse the repository at this point in the history
Authors need a way to get the content box size in integral physical pixels. This allows for the correct sizing of the backing store of a canvas to match the snapped CSS size and prevents moire patterns that arise when the sizes are mismatched.

Currently authors could use devicePixelRatio and rounding in order to approximate this, but due to implementation differences in pixel snapping, can still get the wrong answer. Additionally, this can be affected by position changes which authors cannot currently hook into in a reasonable manner.
  • Loading branch information
dlibby- authored Nov 8, 2019
1 parent b1e43ba commit bc14435
Showing 1 changed file with 37 additions and 4 deletions.
41 changes: 37 additions & 4 deletions resize-observer-1/Overview.bs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ urlPrefix: https://www.w3.org/TR/CSS21/box.html
url: #box-border-area; type: dfn; text: box border area
urlPrefix: https://drafts.csswg.org/css-box-3/
url: #content-area; type: dfn; text: content area
urlPrefix: https://www.w3.org/TR/cssom-view-1/
url: #dom-window-devicepixelratio; type: dfn; text: devicePixelRatio

</pre>
<pre class=link-defaults>
Expand Down Expand Up @@ -135,14 +137,30 @@ It is modeled after {{MutationObserver}} and {{IntersectionObserver}}.

<pre class="idl">
enum ResizeObserverBoxOptions {
"border-box", "content-box"
"border-box", "content-box", "device-pixel-content-box"
};
</pre>

ResizeObserver can observe different kinds of CSS sizes:

* {{border-box}} : size of <a>box border area</a> as defined in CSS2.
* {{content-box}} : size of <a>content area</a> as defined in CSS2.
* {{device-pixel-content-box}} : size of <a>content area</a> as defined in CSS2, in device pixels,
before applying any CSS transforms on the element or its ancestors.
This size must contain integer values.

<p class="note">
The {{device-pixel-content-box}} can be approximated by multiplying <a>devicePixelRatio</a> by the {{content-box}} size.
However, due to browser-specific subpixel snapping behavior,
authors cannot determine the correct way to round this scaled {{content-box}} size.
How a UA computes the device pixel box for an element is implementation-dependent.
One possible implementation could be to multiply the box size and position by the device pixel ratio,
then round both the resulting floating-point size and position of the box to integer values,
in a way that maximizes the quality of the rendered output.

Note that this size can be affected by position changes to the target,
and thus is typically more expensive to observe than the other sizes.
</p>

<pre class="idl">
dictionary ResizeObserverOptions {
Expand Down Expand Up @@ -231,6 +249,7 @@ interface ResizeObserverEntry {
readonly attribute DOMRectReadOnly contentRect;
readonly attribute ResizeObserverSize borderBoxSize;
readonly attribute ResizeObserverSize contentBoxSize;
readonly attribute ResizeObserverSize devicePixelContentBoxSize;
};
</pre>

Expand All @@ -249,6 +268,9 @@ interface ResizeObserverEntry {
: <dfn>contentBoxSize</dfn>
::
{{Element}}'s <a>content rect</a> size when {{ResizeObserverCallback}} is invoked.
: <dfn>devicePixelContentBoxSize</dfn>
::
{{Element}}'s <a>content rect</a> size in integral device pixels when {{ResizeObserverCallback}} is invoked.
</div>

<div dfn-type="method" dfn-for="ResizeObserverEntry">
Expand All @@ -264,15 +286,18 @@ interface ResizeObserverEntry {
4. Set |this|.{{ResizeObserverEntry/contentBoxSize}} slot to result of <a href="#calculate-box-size">
computing size given |target| and observedBox of "content-box"</a>.

5. Set |this|.{{ResizeObserverEntry/contentRect}} to logical |this|.{{ResizeObserverEntry/contentBoxSize}}.
5. Set |this|.{{ResizeObserverEntry/devicePixelContentBoxSize}} slot to result of <a href="#calculate-box-size">
computing size given |target| and observedBox of "device-pixel-content-box"</a>.

6. Set |this|.{{ResizeObserverEntry/contentRect}} to logical |this|.{{ResizeObserverEntry/contentBoxSize}} given |target| and observedBox of "content-box".

6. If |target| is not an SVG element do these steps:
7. If |target| is not an SVG element do these steps:

1. Set |this|.|contentRect|.top to |target|.<a>padding top</a>.

2. Set |this|.|contentRect|.left to |target|.<a>padding left</a>.

7. If |target| is an SVG element do these steps:
8. If |target| is an SVG element do these steps:

1. Set |this|.|contentRect|.top and |this|.contentRect.left to 0.

Expand Down Expand Up @@ -448,6 +473,8 @@ run these steps:

2. Matching size is |entry|.{{ResizeObserverEntry/contentBoxSize}} if |observation|.{{ResizeObservation/observedBox}} is "content-box"

3. Matching size is |entry|.{{ResizeObserverEntry/devicePixelContentBoxSize}} if |observation|.{{ResizeObservation/observedBox}} is "device-pixel-content-box"

4. Set |targetDepth| to the result of <a>calculate depth for node</a> for |observation|.{{ResizeObservation/target}}.

5. Set |shallowestTargetDepth| to |targetDepth| if |targetDepth| < |shallowestTargetDepth|
Expand Down Expand Up @@ -505,6 +532,12 @@ To <dfn>calculate box size</dfn>, given |target| and |observedBox|, run these st

2. Set |computedSize|.blockSize to target's <a>content area</a> block length.

2. If |observedBox| is "device-pixel-content-box"

1. Set |computedSize|.inlineSize to target's <a>content area</a> inline length, in integral device pixels.

2. Set |computedSize|.blockSize to target's <a>content area</a> block length, in integral device pixels.

3. return |computedSize|.

<h3 id="lifetime">ResizeObserver Lifetime</h3>
Expand Down

0 comments on commit bc14435

Please sign in to comment.