GNOME Bugzilla – Bug 360542
Rounded corners have missing pixels
Last modified: 2006-11-05 21:22:08 UTC
Running with HEAD, I see missing pixels in the rounded corners of my titlebar. I'll attach two screen shots, one running metacity from the gnome-2-16 branch and one from HEAD.
Created attachment 74262 [details] gnome-2-16 version, nicely rounded corners (look at the calculator titlebar)
Created attachment 74263 [details] HEAD version with pixels missing in the corners
Oh, that is actually quite ugly, isn't it? Hmm. Let's compare approaches. The widths of each row of transparent pixels are hardcoded in 2.16.0: O = transparent X = not transparent OOOOOXXX = row 0, 5 pixels OOOXXXXX = row 1, 3 pixels OOXXXXXX = row 2, 2 pixels OXXXXXXX = rows 3 and 4, 1 pixel OXXXXXXX XXXXXXXX = subsequent rows, 0 pixels These values were clearly chosen to fit nicely round an arc. In HEAD, because the radius can be any integral value, we calculate the widths of each row of transparent pixels. At present we use the formula 1 + (radius - floor(sqrt(radius*radius - (radius-i)*(radius-i)))) where i is the row number, which varies between 0 and radius-1. For the default setup, which you seem to be using, radius = 5. So this gives us OOOXXXXX = row 0: 1+(5-floor(sqrt(25 - 4*4))) = 3 OOXXXXXX = row 1: 1+(5-floor(sqrt(25 - 3*3))) = 2 OOXXXXXX = row 2: 1+(5-floor(sqrt(25 - 2*2))) = 2 OOXXXXXX = row 3: 1+(5-floor(sqrt(25 - 1*1))) = 2 OXXXXXXX = row 4: 1+(5-floor(sqrt(25 - 0*0))) = 1 XXXXXXXX = subsequent rows, 0 pixels I don't remember where the formula originally came from now, but it gives a decent circular area for most values. But in this case, it's clearly a pretty bad approximation for the original: OOOOOXXX OOOXXXXX OOOXXXXX OOXXXXXX OOXXXXXX versus OOXXXXXX OXXXXXXX OXXXXXXX OXXXXXXX OXXXXXXX XXXXXXXX XXXXXXXX I think we/I need to find a better formula.
(If you can dive in with mathematician-fu and say "oh, you should do this and this", please feel free to; otherwise I will dig around in the libraries and see how the arc routine figures it out, and do it that way.)
Without looking at the formulas but remembering that you had previously tried to round (though with rint), I just replaced floor(x) with floor(x+0.5) in frames.c (i.e. so that it acted like round(x)) where x is those long expressions with sqrts and stuff. Seems to look pretty good, though I think it's not quite identical to the old version (hard to tell at a brief glance, and I'm too lazy too look closer as it's good enough for me). I'll attach a patch. You can look over it and see if that's what you want or whether you need to look closer. :)
Created attachment 74264 [details] [review] s/floor(x)/floor(x + 0.5)/
Oh, good grief. Do you know, when I calculated the figures in comment 3, I was assuming round() instead of floor()? So it would be even worse than I thought! Thanks for the patch. Which theme are you using?
Clearlooks.
So, in your explanation you said you used i=0...radius-1, but the example used 1...radius. If you switch your example to i=0...radius-1 and include the +0.5, then you get OOOOOOXX = row 0: 1+(5-floor(sqrt(25 - 5*5)+0.5)) = 6 OOOXXXXX = row 1: 1+(5-floor(sqrt(25 - 4*4)+0.5)) = 3 OOXXXXXX = row 2: 1+(5-floor(sqrt(25 - 3*3)+0.5)) = 2 OXXXXXXX = row 3: 1+(5-floor(sqrt(25 - 2*2)+0.5)) = 1 OXXXXXXX = row 4: 1+(5-floor(sqrt(25 - 1*1)+0.5)) = 1 XXXXXXXX = subsequent rows, 0 pixels which is 1 pixel off from the 2.16 version; not too bad. It turns out, if we just decrease r-i by a little bit (not for any reason other than "hey, I tried a couple things and here's something that looks good"), then we can get the old answers: 1 + 5 - sqrt(25 - 4.95*4.95) = 5.29; rounds to 5 1 + 5 - sqrt(25 - 3.95*3.95) = 2.93; rounds to 3 1 + 5 - sqrt(25 - 2.95*2.95) = 1.96; rounds to 2 1 + 5 - sqrt(25 - 1.95*1.95) = 1.40; rounds to 1 1 + 5 - sqrt(25 - 0.95*0.95) = 1.09; rounds to 1 Just some food for thought. I'm happy enough with the floor + 0.5 thing; I'll let you worry about the pixel-perfect aesthetics. :)
I'll go with your floor+0.5 solution; it's much better than we have right now and we can tweak it later if needs be. I'll commit it now.