Summary:  Rounding errors in converting cm to px  

Product:  WebKit  Reporter:  BerendJan Wever <skylined>  
Component:  CSS  Assignee:  Nobody <webkitunassigned>  
Status:  NEW   
Severity:  Normal  CC:  eric, hyatt, jamesr, weizhengshen, yevseytsev  
Priority:  P1  
Version:  528+ (Nightly build)  
Hardware:  PC  
OS:  Windows Vista  
Attachments: 

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? 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. 
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