[Top][All Lists]

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

[bug #27782] drawInRect:fromRect:operation:fraction: doesn't work correc

From: Quentin Mathé
Subject: [bug #27782] drawInRect:fromRect:operation:fraction: doesn't work correctly in a flipped view
Date: Tue, 03 Nov 2009 16:37:52 +0000
User-agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6; fr-fr) AppleWebKit/531.9 (KHTML, like Gecko) Version/4.0.3 Safari/531.9

Follow-up Comment #10, bug #27782 (project gnustep):

Looks like the upload went fine this time. :-) I just compiled the test app
and tested it with the Cairo backend.

'draw rep' case doesn't behave as 'draw image' case in flipped coordinates,
so I suppose there is something wrong here. My patch probably a small
adjustment. The rest seems to be fine. NSCopyBits results are weird though.
I'll check what is drawn on Mac OS X.

This test app should be committed to the GNUstep repository I think.

We also need to check cases such as rotated and scaled in flipped
coordinates. Neither your test app or mine cover these yet.

The transformation manipulation doesn't exactly boil down to another flip
because the translation of the flip isn't eliminated (only the scaling is). 
It just does what Cocoa Drawing explains about composite/dissolve methods:
"The most important behavior is that the compositing methods undo any scale
or rotation factors (but not translation factors) applied to the CTM prior to
drawing. If you are drawing in a flipped view or manually applied scaling or
rotation values to the current context, these methods will ignore those

In the patch, this is done with:
newTs.m11 = 1; 
newTs.m12 = 0; 
newTs.m21 = 0; 
newTs.m22 = 1; 

newTs.tX and newTs.tY are let as is because they store the translation.

Before that I do another adjustment to compensate the specific case where the
graphics context is flipped. Typically when m11 sign was -1.5 and is now 1 in
[transform translateXBy: aPoint.x yBy: aPoint.y];
This is necessary because otherwise the drawing location will be interpreted
in the new coordinates orientation (not flipped) and not in the initial one
(flipped).  Figure 3-9 in Cocoa Drawing shows what is expected. If you comment
out this -translateXby:yBy: line you can more easily observe why it is

An alternative to this -translateXBy:yBy: is to detect when canceling
scaling/rotation involves a sign change in newTs on the y scaling (m22) by
handling it as below:

float y = aPoint.y;

newTs.m11 = 1; 
newTs.m12 = 0; 
newTs.m21 = 0; 
newTs.m22 = 1; 

// NOTE: Here we could do check [ctxt isFlipped] but checking the transform
struct directly 
// makes possible to correctly handle the case where the flip transform was
applied manually 
// and where [ctxt isFlipped] will return NO.
if (didWeChangeYScalingSign(newTs.m22, oldTs.m22))
        y = -aPoint.y;

// Move the drawing rectangle

[ctxt GScomposite: [[cache window] gState] toPoint: NSMakePoint(aPoint.x, y)
fromRect: rect operation: op fraction: delta];

This code seems a bit more fragile (and less readable) to me so I used
-translateXBy:yBy: in the patch I submitted. I also think it isn't really
needed to have a toPoint: parameter at the backend level and it could be
cleaner to always make as many CTM adjustments as possible on the AppKit side
rather than splitting them between Gui and the backend.


There is one thing more or less related I don't understand though, the value
of m22 and m11 stay consistent within an application run, but vary between
each run. They oscillate between -2 and -1 when the graphics context is
flipped but without any visible effect. Is this due to some user scale factor
adjustment and why is the scaling not wrong? Or am I missing something related
to matrix maths…

You can add NSLog(@"%0.2f %0.2f", newTs.m11, newTs.m22); before newTs is
manipulated to see what I mean. Just run an app like Gorm two or three times,
the logging will be different with each run.


Reply to this item at:


  Message posté via/par Savannah

reply via email to

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