4 ms·
> It already is. CSS "px" doesn't refer to physical pixels at all, they're called logical pixels. Which on old screens at 100% zoom may map 1:1, but these days
by jan_Inkepa 6y ago
> It already is. CSS "px" doesn't refer to physical pixels at all, they're called logical pixels. Which on old screens at 100% zoom may map 1:1, but these days are more likely to map 2:1 or even 3:1, and with OS and browser zoom levels may be things like 1.666:1 or 2.5:1.
Yeah it's a nightmare if you're doing pixel-art-y games in the browsers, there's last time I checked no way in general to get access to physical pixels anymore, which makes integer-multiple upscaling AFAIK impossible in general. Hurrah. [ disclaimer: The browser rendering stack is complicated enough that I might be wrong. ]
- wffurr 6y agoCSS px * devicePixelRatio = physical pixels I feel your pain about non-integer scaling ratios. The way I hack around it is to set the canvas context to an integer number of device pixels, and then set the CSS size of the canvas to a fractional size: device pixels / DPR. We use this along with some other hacks on keep.google.com and some other sites to map 1:1 to display pixels to try to ensure hardware overlay promotion for the inking surface.
- greggman3 6y agoDoesn't always work (may work for your use case). There are edgecases in the browser where at an HTML level the browser computes a CSS size but at compositing level (where devicePixelRatio is used) it might have clip by pixel here or there. And example, lets say your windows 99 device pixel wide and a DRP of 2.0 and lets say you ask for 2 side by side elements (via flexbox or whatever) each width:50%. At the HTML level the browser will compute there are 49.5 CSS pixels available. It will then compute the size of each 50% as 24.25 CSS pixels but in order to fill the 99 pixels, one of those 2 elements has to be 50 pixels and the other 49. There is no part of the spec that says which side gets 50 and which get 49. Most browser compute 50 for both sides, the pass it up their compositor which will use 50 pixels of one and 49 of the other. The point is, you can't know which one will get which by doing CSSpx * dpr. This is why ResizeObserver device-pixel-content-box was added. So that you can ask the browser what it did.
- jan_Inkepa 6y ago> ResizeObserver TIL. Oh gosh I don't know if I have the brain power to work through all the necessary rendering layers logic to fix up my game engine to make the pixels as they should be, but if I ever do and figure it out, great thanks to you! (and even otherwise, thanks!)
- wffurr 6y agoI will check out that ResizeObserver property. I hack around it by taking the CSS size of the container, finding the closest smaller integer device pixel size, and set the canvas context to that and the canvas CSS size to the fractional size, which can be smaller than the containers CSS size. Basically rounding down.
- greggman3 6y agoHere's a test https://jsgist.org/?src=0cfdcbad01c616047311b2b9ab51bbc3 https://jsgist.org/?src=0cfdcbad01c616047311b2b9ab51bbc3
- tracker1 6y agoPlaying with xterm.js with several fonts trying to get some regularity is/was an exercise in frustration for sure.
- greggman3 6y agoThere is, ResizeObserver -> device-pixel-content-box But ATM it's Chromium browsers only. Some examples on this page https://webglfundamentals.org/webgl/lessons/webgl-resizing-the-canvas.html https://webglfundamentals.org/webgl/lessons/webgl-resizing-t... Bugs filed for other browsers but AFAICT it's not a priority for them. Note: For a pixelated game having this info useful. Also for diagrams, as the user zooms in you'd like to be able to re-render a canvas at native resolution the same way SVG and text gets re-rendered. But, a noticeable problem is static images. You make pixelated image say, 100x50 and display it 4x like this <img src="100x50.png" style="width: 400px; height: 200px; image-rendering: pixelated;"> But, what's the browser supposed to do with that on a screen with 1.25 devicePixelRatio? It will look like crap.
- jan_Inkepa 6y agoAt someone's recommendation a while ago I made a proposal for integer-multiple upscaling - https://github.com/w3c/csswg-drafts/issues/5967 https://github.com/w3c/csswg-drafts/issues/5967 . It feels very niche, especially given how complex the standards already are, but OTOH I'd use it if it were a thing... (Also, that linked page is very cool, and shows how awfully tricky the problem is...none of the proposed solutions work on my iPad, especially not once one zooms in/out in the browser - oh it turns out it was related to browser zoom level - at normal zoom they work (sometimes when I resize the page at normal zoom it works, sometimes it doesn't...). So I guess it's 70% of the way there...but not all the way there).
- greggman3 6y agoThe reason it doesn't work on iPad is because iPad doesn't support the required API. Without that API there is nothing you can except special case per browser and pray. And even then, Safari doesn't change DRP based on zoom level like Firefox and Chrome do so it's currently impossible on Safari period.
- jan_Inkepa 6y agoI've added an event in my calendar to go back to this topic again this day one year from now to see if things have improved any (I skirt with frustration-induced burnout every time it raises its head as relevant, so I need to limit my exposure). Thanks for knowing more than me about this cursed subject matter.