Skip to content

Commit bc14435

Browse files
authored
Add support for device-pixel-content-box-size w3c#3554 (w3c#4476)
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.
1 parent b1e43ba commit bc14435

1 file changed

Lines changed: 37 additions & 4 deletions

File tree

resize-observer-1/Overview.bs

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ urlPrefix: https://www.w3.org/TR/CSS21/box.html
4242
url: #box-border-area; type: dfn; text: box border area
4343
urlPrefix: https://drafts.csswg.org/css-box-3/
4444
url: #content-area; type: dfn; text: content area
45+
urlPrefix: https://www.w3.org/TR/cssom-view-1/
46+
url: #dom-window-devicepixelratio; type: dfn; text: devicePixelRatio
4547

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

136138
<pre class="idl">
137139
enum ResizeObserverBoxOptions {
138-
"border-box", "content-box"
140+
"border-box", "content-box", "device-pixel-content-box"
139141
};
140142
</pre>
141143

142144
ResizeObserver can observe different kinds of CSS sizes:
143145

144146
* {{border-box}} : size of <a>box border area</a> as defined in CSS2.
145147
* {{content-box}} : size of <a>content area</a> as defined in CSS2.
148+
* {{device-pixel-content-box}} : size of <a>content area</a> as defined in CSS2, in device pixels,
149+
before applying any CSS transforms on the element or its ancestors.
150+
This size must contain integer values.
151+
152+
<p class="note">
153+
The {{device-pixel-content-box}} can be approximated by multiplying <a>devicePixelRatio</a> by the {{content-box}} size.
154+
However, due to browser-specific subpixel snapping behavior,
155+
authors cannot determine the correct way to round this scaled {{content-box}} size.
156+
How a UA computes the device pixel box for an element is implementation-dependent.
157+
One possible implementation could be to multiply the box size and position by the device pixel ratio,
158+
then round both the resulting floating-point size and position of the box to integer values,
159+
in a way that maximizes the quality of the rendered output.
160+
161+
Note that this size can be affected by position changes to the target,
162+
and thus is typically more expensive to observe than the other sizes.
163+
</p>
146164

147165
<pre class="idl">
148166
dictionary ResizeObserverOptions {
@@ -231,6 +249,7 @@ interface ResizeObserverEntry {
231249
readonly attribute DOMRectReadOnly contentRect;
232250
readonly attribute ResizeObserverSize borderBoxSize;
233251
readonly attribute ResizeObserverSize contentBoxSize;
252+
readonly attribute ResizeObserverSize devicePixelContentBoxSize;
234253
};
235254
</pre>
236255

@@ -249,6 +268,9 @@ interface ResizeObserverEntry {
249268
: <dfn>contentBoxSize</dfn>
250269
::
251270
{{Element}}'s <a>content rect</a> size when {{ResizeObserverCallback}} is invoked.
271+
: <dfn>devicePixelContentBoxSize</dfn>
272+
::
273+
{{Element}}'s <a>content rect</a> size in integral device pixels when {{ResizeObserverCallback}} is invoked.
252274
</div>
253275

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

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

269-
6. If |target| is not an SVG element do these steps:
294+
7. If |target| is not an SVG element do these steps:
270295

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

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

275-
7. If |target| is an SVG element do these steps:
300+
8. If |target| is an SVG element do these steps:
276301

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

@@ -448,6 +473,8 @@ run these steps:
448473

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

476+
3. Matching size is |entry|.{{ResizeObserverEntry/devicePixelContentBoxSize}} if |observation|.{{ResizeObservation/observedBox}} is "device-pixel-content-box"
477+
451478
4. Set |targetDepth| to the result of <a>calculate depth for node</a> for |observation|.{{ResizeObservation/target}}.
452479

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

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

535+
2. If |observedBox| is "device-pixel-content-box"
536+
537+
1. Set |computedSize|.inlineSize to target's <a>content area</a> inline length, in integral device pixels.
538+
539+
2. Set |computedSize|.blockSize to target's <a>content area</a> block length, in integral device pixels.
540+
508541
3. return |computedSize|.
509542

510543
<h3 id="lifetime">ResizeObserver Lifetime</h3>

0 commit comments

Comments
 (0)