RESOLVED CONFIGURATION CHANGED Bug 53586
Rounding errors in converting cm to px
https://bugs.webkit.org/show_bug.cgi?id=53586
Summary Rounding errors in converting cm to px
Berend-Jan Wever
Reported 2011-02-02 04:55:19 PST
Created attachment 80910 [details] Repro It appears webkit is rounding sizes specified in "cm" down, where other browsers are not. Repro: run the following test in multiple browsers: <!doctype html> <script> for (var i = 0; i < 5; i++) { var iSize = Math.pow(10, i); var o = document.createElement('span'); document.documentElement.appendChild(o); o.style.display = 'block'; o.style.width = iSize + 'cm'; document.write('1cm = ' + (o.clientWidth / iSize) + 'px +/- ~0.' + new Array(i).join('0') + '5<br/>'); } </script> Chrome/Safari both output the same values, with rounding down errors: 1cm = 37px +/- ~0.5 1cm = 37.7px +/- ~0.05 1cm = 37.79px +/- ~0.005 1cm = 37.795px +/- ~0.0005 1cm = 37.7952px +/- ~0.00005 Firefox/MSIE both output the same values, which seem to get rounded correctly: 1cm = 38px +/- ~0.5 1cm = 37.8px +/- ~0.05 1cm = 37.8px +/- ~0.005 1cm = 37.795px +/- ~0.0005 1cm = 37.7953px +/- ~0.00005 Opera seems to agree with FF/MSIE for the most part, but doesn't appear to limit sizes to 32,767 (0x7FFF), so the last two values are not calculated correctly: 1cm = 38px +/- ~0.5 1cm = 37.8px +/- ~0.05 1cm = 37.8px +/- ~0.005 1cm = 32.767px +/- ~0.0005 1cm = 3.2767px +/- ~0.00005
Attachments
Repro (376 bytes, text/html)
2011-02-02 04:55 PST, Berend-Jan Wever
no flags
Sanders Shen
Comment 1 2012-02-24 21:29:10 PST
I think this issue is caused by the implementation of "roundForImpreciseConversion"(Source/WebCore/css/CSSPrimitiveValue.h). It uses "static_cast" to convert a double number to other type, then it would case the precision losing. I modify the logic here as followings: return ((value > max) || (value < min)) ? 0 : static_cast<T>(lround(value)); Then, the Qt porting could get same result with Firefox/MSIE. But, I am not sure whether it has any other side effects. Anyone could explain why we just use "static_cast" here?
yevseytsev
Comment 2 2019-02-08 10:54:53 PST
Hello, I decided to start my contributions to WebKit from some bug triaging, and found out this bug. After reproducing the bug's code (Feb 2019) I actually got the following results for different browsers: SAFARI 1cm = 38px +/- ~0.5 1cm = 37.8px +/- ~0.5 1cm = 37.8px +/- ~0.05 1cm = 37.795px +/- ~0.005 1cm = 37.7953px +/- ~0.0005 FIREFOX 1cm = 38px +/- ~0.5 1cm = 37.8px +/- ~0.5 1cm = 37.8px +/- ~0.05 1cm = 37.795px +/- ~0.005 1cm = 37.7953px +/- ~0.0005 GOOGLE CHROME 1cm = 38px +/- ~0.5 1cm = 37.8px +/- ~0.5 1cm = 37.8px +/- ~0.05 1cm = 37.795px +/- ~0.005 1cm = 37.7953px +/- ~0.0005 OPERA 1cm = 38px +/- ~0.5 1cm = 37.8px +/- ~0.5 1cm = 37.8px +/- ~0.05 1cm = 37.795px +/- ~0.005 1cm = 37.7953px +/- ~0.0005 All the values are the same for all 4 browsers, which means that the bug was fixed. After researching the implementation of "roundForImpreciseConversion" function in Source/WebCore/css/CSSPrimitiveValue.h file I found out the following code: template<typename T> inline T roundForImpreciseConversion(double value) { // Dimension calculations are imprecise, often resulting in values of e.g. // 44.99998. We need to go ahead and round if we're really close to the // next integer value. value += (value < 0) ? -0.01 : +0.01; return ((value > std::numeric_limits<T>::max()) || (value < std::numeric_limits<T>::min())) ? 0 : static_cast<T>(value); } I believe that after Sanders Shen's (weizhengshen@gmail.com) edit (24 Feb, 2012), macpherson@chromium.org did the final edit to "return" function code to fix this bug (20 Mar, 2012). I think this bug is no longer a bug, because any of that 4 browsers does not have any rounding errors. As well we can't talk about WebKit bugs anymore in context of Chrome(desktop) and Opera, because in April 2013, Google and Opera Software announced the transition to the Blink engine. WebKit powers a Google Chrome only on iOS version of the browser.
Ahmad Saleem
Comment 3 2022-08-06 19:08:51 PDT
Latest results across browsers: *** Safari 15.6 on macOS 12.5 *** 1cm = 38px +/- ~0.5 1cm = 37.8px +/- ~0.05 1cm = 37.8px +/- ~0.005 1cm = 37.795px +/- ~0.0005 1cm = 37.7953px +/- ~0.00005 *** Firefox Nightly 105 *** 1cm = 38px +/- ~0.5 1cm = 37.8px +/- ~0.05 1cm = 37.8px +/- ~0.005 1cm = 37.795px +/- ~0.0005 1cm = 37.7953px +/- ~0.00005 *** Chrome Canary 106 *** 1cm = 38px +/- ~0.5 1cm = 37.8px +/- ~0.05 1cm = 37.8px +/- ~0.005 1cm = 37.795px +/- ~0.0005 1cm = 37.7953px +/- ~0.00005 _________ Since all browsers are matching, I am going to mark this as "RESOLVED CONFIGURATION CHANGED" assuming that something along the line fixed it. Thanks!
Note You need to log in before you can comment on or make changes to this bug.