| <!doctype html> |
| <link rel="match" href="devicepixel2-ref.html"> |
| <meta name="assert" content="Resize Observer's reported device pixel content box size should be consistent with the actual pixel-snapped painted box size"> |
| <style> |
| html, body { |
| margin: 0; |
| } |
| .line { |
| width: 100px; |
| display: flex; |
| } |
| .line>* { |
| flex: 1; |
| height: 20px; |
| } |
| </style> |
| <body> |
| <div></div> |
| <script type="module"> |
| import createPatternDataURL from './create-pattern-data-url.js'; |
| |
| const {patternSize, dataURL} = createPatternDataURL(); |
| |
| /** |
| * Set the pattern's size on this element so that it draws where |
| * 1 pixel in the pattern maps to 1 devicePixel and then set |
| * its position so it's aligned to the pattern of the body element. |
| */ |
| function setPattern(elem, x, y) { |
| const oneDevicePixel = 1 / devicePixelRatio; |
| const patternPixels = oneDevicePixel * patternSize; |
| elem.style.backgroundImage = `url("${dataURL}")`; |
| elem.style.backgroundSize = `${patternPixels}px ${patternPixels}px`; |
| elem.style.backgroundPosition = `${-x * oneDevicePixel}px ${-y * oneDevicePixel}px`; |
| } |
| |
| /* |
| This test creates elements like this |
| |
| <body> |
| <div> |
| <div class="line"><div></div><div></div></div> |
| <div class="line"><div></div><div></div><div></div></div> |
| <div class="line"><div></div><div></div><div></div><div></div></div> |
| ... |
| </div> |
| </body> |
| |
| It has the first `<div>` starting at the top left corner of the page, the |
| same as the body so they should both have a devicePixel position of 0,0 |
| |
| The devicePixelContentBoxSize of all the elements is queried with |
| a ResizeObserver. |
| |
| It then sets a repeating background-image, background-size and |
| background-position on the all of the innermost children elements so |
| they have a 4x4 checkerboard image at a size that should draw each pixel |
| of the 4x4 checkerboard pattern in single devicePixels and so they should |
| all align with the same pattern applied in a similar manner to the body. |
| |
| In other words |
| |
| <div class="line"> |
| <div></div><div></div><div></div> |
| </div> |
| |
| The first child will be displayed at left = 0 so its background-position is |
| set to 0px 0px. The second child should be displayed at |
| |
| secondChildLeft = entry(firstChild).devicePixelContentBoxSize[0].inlineSize. |
| |
| The 3rd child should be displayed at |
| |
| thirdChildLeft = entry(firstChild).devicePixelContentBoxSize[0].inlineSize + |
| entry(secondChild).devicePixelContentBoxSize[0].inlineSize |
| |
| Using the children's device-pixel positions (determined as described above), |
| we then set each child's background-position to the negated version of the |
| position that we computed for that child. This effectively makes its pattern's |
| origin match the document origin. |
| |
| If what devicePixelContentBox reports is correct the children's patterns |
| will align with the pattern in the body and the children will be invisible. |
| If what devicePixelContentBox reports is incorrect the patterns will not |
| align and it should be clearly visible. |
| */ |
| |
| const wrapperElem = document.querySelector('div'); |
| |
| const elemToDevicePixelSize = new Map(); |
| |
| function setPatternsUsingSizeInfo(entries) { |
| setPattern(document.body, 0, 0); |
| |
| for (const entry of entries) { |
| elemToDevicePixelSize.set(entry.target, { |
| inlineSize: entry.devicePixelContentBoxSize[0].inlineSize, |
| blockSize: entry.devicePixelContentBoxSize[0].blockSize, |
| }); |
| } |
| |
| let devicePixelY = 0; |
| for (const lineElem of wrapperElem.children) { |
| let devicePixelX = 0; |
| for (const childElem of lineElem.children) { |
| setPattern(childElem, devicePixelX, devicePixelY); |
| const devicePixelSize = elemToDevicePixelSize.get(childElem); |
| devicePixelX += devicePixelSize.inlineSize; |
| } |
| |
| const lineEntry = elemToDevicePixelSize.get(lineElem); |
| const lineHeight = lineEntry.blockSize; |
| devicePixelY += lineHeight; |
| } |
| } |
| |
| const observer = new ResizeObserver(setPatternsUsingSizeInfo); |
| observer.observe(document.body); |
| for (let numFlexItems = 2; numFlexItems < 15; ++numFlexItems) { |
| const lineElem = document.createElement('div'); |
| lineElem.className = 'line'; |
| observer.observe(lineElem, {box:"device-pixel-content-box"}); |
| for (let j = 0; j < numFlexItems; ++j) { |
| const inner = document.createElement('div'); |
| lineElem.appendChild(inner); |
| observer.observe(inner, {box:"device-pixel-content-box"}); |
| } |
| wrapperElem.appendChild(lineElem); |
| } |
| </script> |
| </body> |