[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Graphics Rounding (was Re: Pixel-aligned autoresizing)

From: Riccardo Mottola
Subject: Re: Graphics Rounding (was Re: Pixel-aligned autoresizing)
Date: Mon, 11 Jul 2011 09:23:44 +0200
User-agent: Mozilla/5.0 (Windows NT 5.1; rv:2.0.1) Gecko/20110608 Firefox/4.0.1 SeaMonkey/2.1


Sure. We have this code in NSButtonCell drawImage:withFrame:inView:

position.x = MAX(NSMidX(cellFrame) - (size.width / 2.), 0.);
position.y = MAX(NSMidY(cellFrame) - (size.height / 2.), 0.);

Suppose position.x is 16.5, then rint() would round that to 16, so the image 
will be drawn half a pixel to the left of where it should be.

The problem is if we move the button one point to the right, position.x will be 
17.5, and rint() rounds that to 18, so suddenly the image is drawn right of 
where it should be.  You wouldn't expect moving the button frame to affect the 
position of the image inside, but it does. i.e. whether something is at an even 
or odd coordinate should be unimportant for graphics, but rint() decides which 
way to round based on that.

To my knowledge, rint() doesn't do any advanced rounding. It doesn't try to minimize the error by rounding odd numbers down and even up or something like that, it uses a standard round direction. 16.5 will become 17 as 17.5 will become 18. That is, the round error hasn't a zero expected value.

To prove that, I executed a loop in 0.1 steps and printed out the results:

long float: 16.000000, rounded: 16.000000
long float: 16.100000, rounded: 16.000000
long float: 16.200000, rounded: 16.000000
long float: 16.300000, rounded: 16.000000
long float: 16.400000, rounded: 16.000000
long float: 16.500000, rounded: 17.000000
long float: 16.600000, rounded: 17.000000
long float: 16.700000, rounded: 17.000000
long float: 16.800000, rounded: 17.000000
long float: 16.900000, rounded: 17.000000
long float: 17.000000, rounded: 17.000000
long float: 17.100000, rounded: 17.000000
long float: 17.200000, rounded: 17.000000
long float: 17.300000, rounded: 17.000000
long float: 17.400000, rounded: 17.000000
long float: 17.500000, rounded: 18.000000
long float: 17.600000, rounded: 18.000000
long float: 17.700000, rounded: 18.000000
long float: 17.800000, rounded: 18.000000
long float: 17.900000, rounded: 18.000000

As you see, it is consistent. rint() man page says on linux:

The nearbyint() functions round their argument to an integer value in floating-point format, using the current rounding direction (see fesâ
       etround(3)) and without raising the inexact exception.

rint() does the same. The point is "using the current rounding direction".

I don't know if the rint() behaviour is consistent among math libraries.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]