- From: Mikko Rantalainen <mikko.rantalainen@peda.net>
- Date: Fri, 04 Mar 2005 11:10:05 +0200
- To: www-style@w3.org
Ben Curtis wrote: >> This truly is a user agent problem and not a CSS problem, and may >> disappear as UAs become more precise. > > This is a misunderstanding of the problem. It is not a math error, but > rather the accuracy of math that is the problem. I don't agree. We just have to get comfortable with the idea that two elements with "width: 50%" may have a single pixel difference in width. > Say I have 4 floating divs, all width:25%. The viewport is 800px wide, > so each is 200px and they fit side by side. I shrink the viewport to > 798px, and each div is now: > > round(798 * 0.25) = round(199.5) = 200px > > ....totalling 800px, or 2px more than my viewport, causing the last div > to drop below the others. I shrink it to 797px, and each div is now: > > round(797 * 0.25) = round(199.25) = 199px > > ....totalling 796px, or 1px short of my viewport, even though they total > 100% of the width. This is exactly the error in Gecko engine. See https://bugzilla.mozilla.org/show_bug.cgi?id=63336#c39 for example. The thing is, you MUST NOT round the layout coordinates while computing "width" or "height". The correct method is to use floating point numbers for top,left coordinates and then do x1=round(left); x2=round(left+width); // != round(left) + round(width) !! y1=round(top); y2=round(top+height); // != round(top) + round(height) !! (origin at top left corner) I think CSS DOM (is that the right term to use?) is allowed to return floating point numbers for all top,left,....,width,height so you're not required to round anywhere else but in the final rendering stage. > No matter how precise the UA is, this will be true. The only solution > is the elimination of pixels (either by pixels so fine the human eye > cannot discern them or fudging through anti-aliasing vector-based > drawing). Or just render some of the boxes with different width. If you have two elements (one blue and one red) with "width: 50%" and three pixels to fill you have'll end up with two red pixels and one blue pixel OR one red pixel and two blue pixels. In simple case like this one could use antialiasing and select average for the middle pixel. But antialiasing correctly isn't that easy: to get correct results in case like this <div style="color: red; width: 20%"> <div style="color: blue; width: 10%"> <div style="color: green; width: 30%"> <div style="color: yellow; width: 20%"> <div style="color: black; width: 20%"> when you have space for one pixel in layout, you would have to compute weighted average of 5 elements to get correct pixel color. A more complex case would be a table with some elements with colspan and rowspan so antialiasing engine would have to compute areas for every element. And that table would hit the target pixel only partially. Throw in background images and you're in a mess you really don't want to be in. An "easy" way would be to supersample the canvas 10x and downscale for the resulting image. But you would still have to use the correct rounding method (above) to get the *correct* supersampled image in the first case. And supersampling would hit CPU really hard for nearly vanishing improvement in rendering. -- Mikko
Received on Friday, 4 March 2005 09:10:10 UTC