[Top][All Lists]

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

Re: Pixel-aligned autoresizing

From: Fred Kiefer
Subject: Re: Pixel-aligned autoresizing
Date: Wed, 06 Jul 2011 21:18:06 +0200
User-agent: Mozilla/5.0 (X11; U; Linux x86_64; de; rv: Gecko/20110616 SUSE/3.1.11 Thunderbird/3.1.11

On 06.07.2011 11:19, Eric Wasylishen wrote:
Hi Fred,

On 2011-07-06, at 2:32 AM, Fred Kiefer wrote:

On 05.07.2011 22:15, Eric Wasylishen wrote:

In the last month I was looking in to making GS's drawing output
match cocoa exactly, in particular, getting rid of rounding in the

One of the problems I encountered is GS can give autoresizing views
fractional positions/sizes, whereas when Cocoa autoresizes views it
only ever sizes them to pixel-aligned rects. The problem with GS's
current behaviour is it will make UI elements blurry if we get rid of
rounding in the backend.

Attached is a preliminary patch* which switches to Cocoa's behaviour.
I wanted to ask for feedback as to whether this is a reasonable patch
to apply.

The patch has to do a bit more than simply adding rounding to -
(void) resizeWithOldSuperviewSize: (NSSize)oldSize, because if we
just round _frame, we will lose track of where a view originally was.
I add a new ivar _autoresizingFrameError which stores the difference
between the rounded _frame, and what _frame would be without
rounding. The only slightly messy bit of the patch is that any parts
of the code that modify _frame directly should also set
_autoresizingFrameError to {0, 0}.

One result of this patch will be that calling -frame after a call to
-setFrame: with fractional coordinates will return a different result
than the one we provided.

Hm, that shouldn't be the case. -setFrame: still sets the _frame ivar to 
whatever it is passed, and -frame still returns _frame unmodified.

The only difference in -setFrame:'s behaviour (and all other methods that 
modified _frame directly) is that it will have the side effect of clearing the 
_autoresizingFrameError, but this isn't directly observable. The value of 
_autoresizingFrameError is only used inside -resizeWithOldSuperviewSize: to 
compute the new size.

Sorry, I was completely unclear in my previous mail. What I wanted to say was that after setFrame: you may get back a different frame although the only thing that happened was a call to super views setFrame: method with almost identical values as it had before. What I didn't realize was that this will get worse, when a rotation is involved. The method -convertRectToBase: will return a much bigger rectangle in that case and the call to -convertRectFromBase: will only make it worse.

I just checked on Cocoa and as expected this
isn't the case there. For this reason I am strongly against this patch,
although I fully support the goal you are aiming at. We need to come up
with a different way for it.

Assuming there isn't actually a problem I'm overlooking, the patch probably 
needs to add some extra documentation explaining what is going on :-)

Basically wee need to ensure that all drawing operations that are
initiated by the gui drawing code get pixel aligned. Somebody will have
to test whether this is true for all drawing operations, that is, when I
use an NSBezierPath with fractional coordinates to draw into a NSView,
will the result be blurred? I expect this to be the case, which means that we 
cannot put the pixel alignment directly into the backend, but need to do it in 
our own drawing code. The next level would be the functions in Functions.m. 
What will be the result if we feed them with fractional coordinates? And so on 
to determine the level of intervention that is needed.

Agreed. Most of that work is already done in GSTest's PixelExactDrawing-test, 
and you can toggle between what GS is rendering and a screen captures from OS 
X. Drawing with NSBezierPath and fractional coordinates should produce blurred 
output. Same for all of the ops in Functions.m which I've checked.

Thank you, I had forgotten about these new test cases. I will have to recompile GSTest to see it.

[*] One thing I would change in the patch is instead of rounding
using floor(), I would call -centerScanRect: so that the
pixel-alignment takes in to account the transformation matrix of the
current view.

Good point, this method seems to be better suited. Are you aware of the
warnings in that method?

Yes. One thing we could do is simply return the passed rect unmodified if 
[[NSGraphicsContext currentContext] isDrawingToScreen] is NO. Not sure if Cocoa 
does that but it would make sense to, I think.

That would do.

reply via email to

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